diff options
| author | Frédéric Desbiens <[email protected]> | 2026-06-08 10:01:32 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-06-08 10:01:32 +0200 |
| commit | 87ab09cce305eb9cd4aacac4e8c62af72f665bff (patch) | |
| tree | dd062ebbea5235d1921c64b396bf7e4ce79e9e15 /ports | |
| parent | 9ab0cf9683f832cdb48e2099533a5b06a3afcd64 (diff) | |
| parent | 730b61874bc5cf40768987605ae5187fde0fa1e2 (diff) | |
Merge pull request #544 from eclipse-threadx/devv6.5.1.202602_rel
Merging changes for the v.6.5.1.202602 release
Diffstat (limited to 'ports')
451 files changed, 15611 insertions, 4905 deletions
diff --git a/ports/arc_em/metaware/example_build/sample_threadx/sample_threadx.c b/ports/arc_em/metaware/example_build/sample_threadx/sample_threadx.c index 6ce6e0d4..8369fbbc 100644 --- a/ports/arc_em/metaware/example_build/sample_threadx/sample_threadx.c +++ b/ports/arc_em/metaware/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arc_em/metaware/example_build/sample_threadx/vectors.s b/ports/arc_em/metaware/example_build/sample_threadx/vectors.s index eeb9ba2a..452f536b 100644 --- a/ports/arc_em/metaware/example_build/sample_threadx/vectors.s +++ b/ports/arc_em/metaware/example_build/sample_threadx/vectors.s @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + .file "vectors.s" .section .ivt,text diff --git a/ports/arc_em/metaware/inc/tx_port.h b/ports/arc_em/metaware/inc/tx_port.h index 34ca8019..162915b2 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARCv2_EM/MetaWare Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arc_hs/metaware/example_build/sample_threadx/sample_threadx.c b/ports/arc_hs/metaware/example_build/sample_threadx/sample_threadx.c index 6ce6e0d4..8369fbbc 100644 --- a/ports/arc_hs/metaware/example_build/sample_threadx/sample_threadx.c +++ b/ports/arc_hs/metaware/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arc_hs/metaware/example_build/sample_threadx/vectors.s b/ports/arc_hs/metaware/example_build/sample_threadx/vectors.s index eeb9ba2a..452f536b 100644 --- a/ports/arc_hs/metaware/example_build/sample_threadx/vectors.s +++ b/ports/arc_hs/metaware/example_build/sample_threadx/vectors.s @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + .file "vectors.s" .section .ivt,text diff --git a/ports/arc_hs/metaware/inc/tx_port.h b/ports/arc_hs/metaware/inc/tx_port.h index 7c5dc6de..8f0432b2 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARC_HS/MetaWare Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arm11/ac5/example_build/sample_threadx.c b/ports/arm11/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/arm11/ac5/example_build/sample_threadx.c +++ b/ports/arm11/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm11/ac5/inc/tx_port.h b/ports/arm11/ac5/inc/tx_port.h index b1bf6e36..17dff9a4 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm11/gnu/example_build/sample_threadx.c b/ports/arm11/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/arm11/gnu/example_build/sample_threadx.c +++ b/ports/arm11/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm11/gnu/inc/tx_port.h b/ports/arm11/gnu/inc/tx_port.h index 259ad092..c0cb95f6 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm11/iar/example_build/sample_threadx.c b/ports/arm11/iar/example_build/sample_threadx.c index f9d0e94a..e702053e 100644 --- a/ports/arm11/iar/example_build/sample_threadx.c +++ b/ports/arm11/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm11/iar/inc/tx_port.h b/ports/arm11/iar/inc/tx_port.h index 52b43a86..bb96d714 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arm9/ac5/example_build/sample_threadx.c b/ports/arm9/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/arm9/ac5/example_build/sample_threadx.c +++ b/ports/arm9/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm9/ac5/inc/tx_port.h b/ports/arm9/ac5/inc/tx_port.h index e9dc6430..4e62cd5e 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm9/gnu/example_build/sample_threadx.c b/ports/arm9/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/arm9/gnu/example_build/sample_threadx.c +++ b/ports/arm9/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm9/gnu/inc/tx_port.h b/ports/arm9/gnu/inc/tx_port.h index 4597b252..4cb35304 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm9/iar/example_build/sample_threadx.c b/ports/arm9/iar/example_build/sample_threadx.c index 56f7cd55..544f30cc 100644 --- a/ports/arm9/iar/example_build/sample_threadx.c +++ b/ports/arm9/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/arm9/iar/inc/tx_port.h b/ports/arm9/iar/inc/tx_port.h index e4411ae6..20331a7b 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/c667x/ccs/example_build/include/C66XX.h b/ports/c667x/ccs/example_build/include/C66XX.h index 80507ca2..ba1bfdc0 100644 --- a/ports/c667x/ccs/example_build/include/C66XX.h +++ b/ports/c667x/ccs/example_build/include/C66XX.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /****************************************************************************** TMS320C66xx KeyStone Multicore DSP Software Development Kit (SDK). Rev 2A. Definitions, macros and API functions for DSP Environment. diff --git a/ports/c667x/ccs/example_build/include/TA66XX_DSP.h b/ports/c667x/ccs/example_build/include/TA66XX_DSP.h index ba3fa341..46094815 100644 --- a/ports/c667x/ccs/example_build/include/TA66XX_DSP.h +++ b/ports/c667x/ccs/example_build/include/TA66XX_DSP.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /****************************************************************************** TORNADO AMC modules Software Development Kit (SDK). Rev 4A. General definitions and API functions. diff --git a/ports/c667x/ccs/example_build/include/TA66XX_DSP_BC.h b/ports/c667x/ccs/example_build/include/TA66XX_DSP_BC.h index 028ce336..8ad2ae8a 100644 --- a/ports/c667x/ccs/example_build/include/TA66XX_DSP_BC.h +++ b/ports/c667x/ccs/example_build/include/TA66XX_DSP_BC.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /****************************************************************************** TORNADO AMC modules Software Development Kit (SDK). Rev 4A. Definitions, macros and API functions for DSP Environment. diff --git a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.c b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.c index 31e8056b..c9630103 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.c +++ b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /* * board_setup.c * diff --git a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.h b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.h index 9e252dcd..2ead869c 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.h +++ b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/board_setup.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /* * board_setup.h * diff --git a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/sample_threadx.c b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/sample_threadx.c index a97ce125..5e7228eb 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_c6678evm/sample_threadx.c +++ b/ports/c667x/ccs/example_build/sample_threadx_c6678evm/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ @@ -89,7 +100,7 @@ void tx_application_define(void *first_unused_memory) CHAR *pointer = TX_NULL; UINT status; - /* Enable event tracing using the global �trace_buffer� memory and supporting + /* Enable event tracing using the global �trace_buffer� memory and supporting a maximum of TRACE_OBJECTS_COUNT ThreadX objects in the registry. */ if ((status = tx_trace_enable(tx_trace_buffer, TRACE_BUFFER_SIZE, TRACE_OBJECTS_COUNT)) != TX_SUCCESS) { diff --git a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.c b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.c index e5b8a0bf..12d79065 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.c +++ b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /* * board_setup.c * diff --git a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.h b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.h index a65e3b9d..a68661f3 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.h +++ b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/board_setup.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /* * board_setup.h * diff --git a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/sample_threadx.c b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/sample_threadx.c index a97ce125..5e7228eb 100644 --- a/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/sample_threadx.c +++ b/ports/c667x/ccs/example_build/sample_threadx_ta6678fmc/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ @@ -89,7 +100,7 @@ void tx_application_define(void *first_unused_memory) CHAR *pointer = TX_NULL; UINT status; - /* Enable event tracing using the global �trace_buffer� memory and supporting + /* Enable event tracing using the global �trace_buffer� memory and supporting a maximum of TRACE_OBJECTS_COUNT ThreadX objects in the registry. */ if ((status = tx_trace_enable(tx_trace_buffer, TRACE_BUFFER_SIZE, TRACE_OBJECTS_COUNT)) != TX_SUCCESS) { diff --git a/ports/c667x/ccs/inc/tx_port.h b/ports/c667x/ccs/inc/tx_port.h index 6f5a9838..229014ea 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX C667x/TI Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a12/ac6/example_build/sample_threadx.c b/ports/cortex_a12/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a12/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a12/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a12/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a12/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a12/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a12/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a12/ac6/inc/tx_port.h b/ports/cortex_a12/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a12/gnu/example_build/sample_threadx.c b/ports/cortex_a12/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a12/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a12/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a12/gnu/example_build/v7.h b/ports/cortex_a12/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a12/gnu/example_build/v7.h +++ b/ports/cortex_a12/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a12/gnu/inc/tx_port.h b/ports/cortex_a12/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/ac6/example_build/sample_threadx.c b/ports/cortex_a15/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a15/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a15/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a15/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a15/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a15/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a15/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a15/ac6/inc/tx_port.h b/ports/cortex_a15/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/gnu/example_build/sample_threadx.c b/ports/cortex_a15/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a15/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a15/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a15/gnu/example_build/v7.h b/ports/cortex_a15/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a15/gnu/example_build/v7.h +++ b/ports/cortex_a15/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a15/gnu/inc/tx_port.h b/ports/cortex_a15/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/iar/example_build/sample_threadx.c b/ports/cortex_a15/iar/example_build/sample_threadx.c index afbd4ea8..ed04e3b6 100644 --- a/ports/cortex_a15/iar/example_build/sample_threadx.c +++ b/ports/cortex_a15/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a15/iar/inc/tx_port.h b/ports/cortex_a15/iar/inc/tx_port.h index ca868f64..18741e4c 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A15/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a17/ac6/example_build/sample_threadx.c b/ports/cortex_a17/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a17/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a17/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a17/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a17/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a17/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a17/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a17/ac6/inc/tx_port.h b/ports/cortex_a17/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a17/gnu/example_build/sample_threadx.c b/ports/cortex_a17/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a17/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a17/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a17/gnu/example_build/v7.h b/ports/cortex_a17/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a17/gnu/example_build/v7.h +++ b/ports/cortex_a17/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a17/gnu/inc/tx_port.h b/ports/cortex_a17/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a34/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a34/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a34/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a34/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a34/ac6/inc/tx_port.h b/ports/cortex_a34/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a34/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a34/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a34/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a34/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a34/gnu/inc/tx_port.h b/ports/cortex_a34/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a35/ac6/inc/tx_port.h b/ports/cortex_a35/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a35/gnu/inc/tx_port.h b/ports/cortex_a35/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ac5/example_build/sample_threadx.c b/ports/cortex_a5/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a5/ac5/example_build/sample_threadx.c +++ b/ports/cortex_a5/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/ac5/inc/tx_port.h b/ports/cortex_a5/ac5/inc/tx_port.h index 3c046e95..60f212fc 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ac6/example_build/sample_threadx.c b/ports/cortex_a5/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a5/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a5/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a5/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a5/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a5/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/ac6/inc/tx_port.h b/ports/cortex_a5/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ghs/example_build/sample_threadx.c b/ports/cortex_a5/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a5/ghs/example_build/sample_threadx.c +++ b/ports/cortex_a5/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/ghs/inc/tx_port.h b/ports/cortex_a5/ghs/inc/tx_port.h index e9e0b876..f6e4fefc 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/gnu/example_build/sample_threadx.c b/ports/cortex_a5/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a5/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a5/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/gnu/example_build/v7.h b/ports/cortex_a5/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a5/gnu/example_build/v7.h +++ b/ports/cortex_a5/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a5/gnu/inc/tx_port.h b/ports/cortex_a5/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/iar/example_build/sample_threadx.c b/ports/cortex_a5/iar/example_build/sample_threadx.c index 56f7cd55..544f30cc 100644 --- a/ports/cortex_a5/iar/example_build/sample_threadx.c +++ b/ports/cortex_a5/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5/iar/inc/tx_port.h b/ports/cortex_a5/iar/inc/tx_port.h index 5ce81a27..5893398b 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a53/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a53/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a53/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a53/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a53/ac6/inc/tx_port.h b/ports/cortex_a53/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a53/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a53/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a53/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a53/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a53/gnu/inc/tx_port.h b/ports/cortex_a53/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a55/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a55/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a55/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a55/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a55/ac6/inc/tx_port.h b/ports/cortex_a55/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a55/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a55/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a55/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a55/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a55/gnu/inc/tx_port.h b/ports/cortex_a55/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a57/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a57/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a57/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a57/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a57/ac6/inc/tx_port.h b/ports/cortex_a57/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a57/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a57/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a57/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a57/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a57/gnu/inc/tx_port.h b/ports/cortex_a57/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c index d37d4c27..df7f89c3 100644 --- a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + // ---------------------------------------------------------- // GIC400 - Generic Interrupt Controller // diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h index aca064c3..f7f0ce7a 100644 --- a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + // ---------------------------------------------------------- // GIC400 - Generic Interrupt Controller // Header diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c index 3e4c45a5..ff7ff826 100644 --- a/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a5x/ac6/inc/tx_port.h b/ports/cortex_a5x/ac6/inc/tx_port.h index c679690c..a05ca47d 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x/ARM Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a65/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a65/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a65/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a65/ac6/inc/tx_port.h b/ports/cortex_a65/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a65/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a65/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a65/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a65/gnu/inc/tx_port.h b/ports/cortex_a65/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65ae/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a65ae/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a65ae/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a65ae/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a65ae/ac6/inc/tx_port.h b/ports/cortex_a65ae/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65ae/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a65ae/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a65ae/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a65ae/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a65ae/gnu/inc/tx_port.h b/ports/cortex_a65ae/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ac5/example_build/sample_threadx.c b/ports/cortex_a7/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a7/ac5/example_build/sample_threadx.c +++ b/ports/cortex_a7/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/ac5/inc/tx_port.h b/ports/cortex_a7/ac5/inc/tx_port.h index 088fc91f..8ce4b0dc 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ac6/example_build/sample_threadx.c b/ports/cortex_a7/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a7/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a7/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a7/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a7/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a7/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/ac6/inc/tx_port.h b/ports/cortex_a7/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ghs/example_build/sample_threadx.c b/ports/cortex_a7/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a7/ghs/example_build/sample_threadx.c +++ b/ports/cortex_a7/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/ghs/inc/tx_port.h b/ports/cortex_a7/ghs/inc/tx_port.h index 7fa32537..cbd64400 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/gnu/example_build/sample_threadx.c b/ports/cortex_a7/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a7/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a7/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/gnu/example_build/v7.h b/ports/cortex_a7/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a7/gnu/example_build/v7.h +++ b/ports/cortex_a7/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a7/gnu/inc/tx_port.h b/ports/cortex_a7/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/iar/example_build/sample_threadx.c b/ports/cortex_a7/iar/example_build/sample_threadx.c index 02183317..011ee398 100644 --- a/ports/cortex_a7/iar/example_build/sample_threadx.c +++ b/ports/cortex_a7/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a7/iar/inc/tx_port.h b/ports/cortex_a7/iar/inc/tx_port.h index 90477b76..9e8b8583 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/IAR Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a72/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a72/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a72/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a72/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a72/ac6/inc/tx_port.h b/ports/cortex_a72/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a72/gnu/inc/tx_port.h b/ports/cortex_a72/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a73/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a73/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a73/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a73/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a73/ac6/inc/tx_port.h b/ports/cortex_a73/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a73/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a73/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a73/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a73/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a73/gnu/inc/tx_port.h b/ports/cortex_a73/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a75/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a75/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a75/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a75/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a75/ac6/inc/tx_port.h b/ports/cortex_a75/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a75/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a75/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a75/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a75/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a75/gnu/inc/tx_port.h b/ports/cortex_a75/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a76/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a76/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a76/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a76/ac6/inc/tx_port.h b/ports/cortex_a76/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a76/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a76/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a76/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a76/gnu/inc/tx_port.h b/ports/cortex_a76/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76ae/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a76ae/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a76ae/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a76ae/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a76ae/ac6/inc/tx_port.h b/ports/cortex_a76ae/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76ae/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a76ae/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a76ae/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a76ae/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a76ae/gnu/inc/tx_port.h b/ports/cortex_a76ae/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a77/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a77/ac6/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a77/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a77/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a77/ac6/inc/tx_port.h b/ports/cortex_a77/ac6/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a77/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a77/gnu/example_build/sample_threadx/sample_threadx.c index 17cceb01..c9d1657e 100644 --- a/ports/cortex_a77/gnu/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a77/gnu/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a77/gnu/inc/tx_port.h b/ports/cortex_a77/gnu/inc/tx_port.h index e5352338..74ec1557 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ac5/example_build/sample_threadx.c b/ports/cortex_a8/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a8/ac5/example_build/sample_threadx.c +++ b/ports/cortex_a8/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/ac5/inc/tx_port.h b/ports/cortex_a8/ac5/inc/tx_port.h index 7dc9a522..3c32a273 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ac6/example_build/sample_threadx.c b/ports/cortex_a8/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a8/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a8/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a8/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a8/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a8/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/ac6/inc/tx_port.h b/ports/cortex_a8/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ghs/example_build/sample_threadx.c b/ports/cortex_a8/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a8/ghs/example_build/sample_threadx.c +++ b/ports/cortex_a8/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/ghs/inc/tx_port.h b/ports/cortex_a8/ghs/inc/tx_port.h index d9dd3413..d2c06933 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/gnu/example_build/sample_threadx.c b/ports/cortex_a8/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a8/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a8/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/gnu/example_build/v7.h b/ports/cortex_a8/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a8/gnu/example_build/v7.h +++ b/ports/cortex_a8/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a8/gnu/inc/tx_port.h b/ports/cortex_a8/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/iar/example_build/sample_threadx.c b/ports/cortex_a8/iar/example_build/sample_threadx.c index afbd4ea8..ed04e3b6 100644 --- a/ports/cortex_a8/iar/example_build/sample_threadx.c +++ b/ports/cortex_a8/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a8/iar/inc/tx_port.h b/ports/cortex_a8/iar/inc/tx_port.h index 940d7f68..b8512373 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a9/ac5/example_build/sample_threadx.c b/ports/cortex_a9/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a9/ac5/example_build/sample_threadx.c +++ b/ports/cortex_a9/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/ac5/inc/tx_port.h b/ports/cortex_a9/ac5/inc/tx_port.h index 0c145156..1dcd4856 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/ac6/example_build/sample_threadx.c b/ports/cortex_a9/ac6/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a9/ac6/example_build/sample_threadx.c +++ b/ports/cortex_a9/ac6/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a9/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a9/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_a9/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/ac6/inc/tx_port.h b/ports/cortex_a9/ac6/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/ghs/example_build/sample_threadx.c b/ports/cortex_a9/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a9/ghs/example_build/sample_threadx.c +++ b/ports/cortex_a9/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/ghs/inc/tx_port.h b/ports/cortex_a9/ghs/inc/tx_port.h index 75e76900..fa6eaef9 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/gnu/example_build/sample_threadx.c b/ports/cortex_a9/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_a9/gnu/example_build/sample_threadx.c +++ b/ports/cortex_a9/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/gnu/example_build/v7.h b/ports/cortex_a9/gnu/example_build/v7.h index c18b945c..1133b0ac 100644 --- a/ports/cortex_a9/gnu/example_build/v7.h +++ b/ports/cortex_a9/gnu/example_build/v7.h @@ -37,7 +37,6 @@ void disableInterrupts(void); void invalidateCaches_IS(void); void cleanInvalidateDCache(void); -void invalidateCaches_IS(void); void enableCaches(void); void disableCaches(void); void invalidateCaches(void); diff --git a/ports/cortex_a9/gnu/inc/tx_port.h b/ports/cortex_a9/gnu/inc/tx_port.h index f0153046..8bd1327a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/iar/example_build/sample_threadx.c b/ports/cortex_a9/iar/example_build/sample_threadx.c index afbd4ea8..ed04e3b6 100644 --- a/ports/cortex_a9/iar/example_build/sample_threadx.c +++ b/ports/cortex_a9/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_a9/iar/inc/tx_port.h b/ports/cortex_a9/iar/inc/tx_port.h index 46f042a9..29a39a8a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m0/ac5/example_build/sample_threadx.c b/ports/cortex_m0/ac5/example_build/sample_threadx.c index dd5ee155..66d68120 100644 --- a/ports/cortex_m0/ac5/example_build/sample_threadx.c +++ b/ports/cortex_m0/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ 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 b16b3e20..3a585477 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 @@ -169,6 +169,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; 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 STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOVS r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m0/ac5/inc/tx_port.h b/ports/cortex_m0/ac5/inc/tx_port.h index f163f1c6..99a627cc 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m0/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_m0/ac6/example_build/sample_threadx/sample_threadx.c index 01f48910..cda6927f 100644 --- a/ports/cortex_m0/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_m0/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m0/ac6/inc/tx_port.h b/ports/cortex_m0/ac6/inc/tx_port.h index 9c9e6470..fab23b82 100644 --- a/ports/cortex_m0/ac6/inc/tx_port.h +++ b/ports/cortex_m0/ac6/inc/tx_port.h @@ -355,7 +355,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC6 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m0/gnu/example_build/sample_threadx.c b/ports/cortex_m0/gnu/example_build/sample_threadx.c index 01f48910..cda6927f 100644 --- a/ports/cortex_m0/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m0/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ 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 e9dfb329..36738f3d 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 @@ -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 STR r1, [r0, #0x14] // Setup SysTick Reload Value LDR r1, =0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m0/gnu/inc/tx_port.h b/ports/cortex_m0/gnu/inc/tx_port.h index 9b315869..48c3824e 100644 --- a/ports/cortex_m0/gnu/inc/tx_port.h +++ b/ports/cortex_m0/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -322,11 +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"); if (__get_ipsr_value() == 0) { interrupt_save = __get_primask_value(); __enable_interrupts(); __restore_interrupts(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -355,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif 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 d798994e..6019b299 100644 --- a/ports/cortex_m0/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m0/gnu/src/tx_thread_system_return.S @@ -5,11 +5,14 @@ @ * terms of the MIT License which is available at @ * https://opensource.org/licenses/MIT. @ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ +* SPDX-License-Identifier: MIT +**************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). + + +/**************************************************************************/ + @/**************************************************************************/ @/** */ @/** ThreadX Component */ @@ -72,12 +75,15 @@ _tx_thread_system_return: LDR r0, =0x10000000 @ Load PENDSVSET bit LDR r1, =0xE000ED04 @ Load NVIC base STR r0, [r1] @ 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 MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK CPSIE i @ Enable interrupts MSR PRIMASK, r1 @ Restore original interrupt posture + ISB #0xF @ Flush pipeline _isr_context: BX lr @ Return to caller @/* } */ diff --git a/ports/cortex_m0/iar/example_build/sample_threadx.c b/ports/cortex_m0/iar/example_build/sample_threadx.c index 8f1d9757..081a200e 100644 --- a/ports/cortex_m0/iar/example_build/sample_threadx.c +++ b/ports/cortex_m0/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ 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 cec6e9b2..991f7809 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 @@ -118,6 +118,9 @@ _tx_initialize_low_level: ; /* Configure SysTick. */ ; 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 STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOVS r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m0/iar/inc/tx_port.h b/ports/cortex_m0/iar/inc/tx_port.h index af5f58bb..7951a30f 100644 --- a/ports/cortex_m0/iar/inc/tx_port.h +++ b/ports/cortex_m0/iar/inc/tx_port.h @@ -313,6 +313,7 @@ __istate_t interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_IPSR() == 0) { interrupt_save = __get_interrupt_state(); @@ -338,7 +339,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 da8a481e..9426a137 100644 --- a/ports/cortex_m0/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m0/iar/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 @@ -7,6 +8,8 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ + +; Some portions generated by Gemini (Gemini 2.0 Flash). ; ; ;/**************************************************************************/ @@ -68,6 +71,8 @@ _tx_thread_system_return: LDR r0, =0x10000000 ; Load PENDSVSET bit LDR r1, =0xE000ED04 ; Load NVIC base STR r0, [r1] ; 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 diff --git a/ports/cortex_m0/keil/example_build/sample_threadx.c b/ports/cortex_m0/keil/example_build/sample_threadx.c index dd5ee155..66d68120 100644 --- a/ports/cortex_m0/keil/example_build/sample_threadx.c +++ b/ports/cortex_m0/keil/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ 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 b16b3e20..3a585477 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 @@ -169,6 +169,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; 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 STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOVS r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m0/keil/inc/tx_port.h b/ports/cortex_m0/keil/inc/tx_port.h index f163f1c6..99a627cc 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c b/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c index df82f09b..da1556e1 100644 --- a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c +++ b/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/cortex_m23/ac6/inc/tx_port.h b/ports/cortex_m23/ac6/inc/tx_port.h index 5ae0b62b..70fe97f9 100644 --- a/ports/cortex_m23/ac6/inc/tx_port.h +++ b/ports/cortex_m23/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -376,6 +378,7 @@ unsigned int was_masked; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (_get_ipsr() == 0) { was_masked = __disable_irq(); @@ -391,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 d85981da..c0bfe023 100644 --- a/ports/cortex_m23/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m23/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: LDR r0, =0x10000000 // Load PENDSVSET bit LDR r1, =0xE000ED04 // Load ICSR address STR r0, [r1] // 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 diff --git a/ports/cortex_m23/gnu/inc/tx_port.h b/ports/cortex_m23/gnu/inc/tx_port.h index b1eab9e3..dad88dfb 100644 --- a/ports/cortex_m23/gnu/inc/tx_port.h +++ b/ports/cortex_m23/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -389,11 +391,13 @@ 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() == 0) { interrupt_save = __get_primask_value(); __enable_interrupts(); __restore_interrupts(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -422,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 a14fdba3..ca5408d7 100644 --- a/ports/cortex_m23/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m23/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,12 +76,15 @@ _tx_thread_system_return: LDR r0, =0x10000000 // Load PENDSVSET bit LDR r1, =0xE000ED04 // Load ICSR address STR r0, [r1] // 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 MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline _isr_context: BX lr // Return to caller // } diff --git a/ports/cortex_m23/iar/inc/tx_port.h b/ports/cortex_m23/iar/inc/tx_port.h index be6bebd5..a02e4e6a 100644 --- a/ports/cortex_m23/iar/inc/tx_port.h +++ b/ports/cortex_m23/iar/inc/tx_port.h @@ -399,6 +399,7 @@ __istate_t interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_IPSR() == 0) { interrupt_save = __get_interrupt_state(); @@ -414,7 +415,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 91ef52c7..da4b6d04 100644 --- a/ports/cortex_m23/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m23/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 */ @@ -65,6 +68,8 @@ _tx_thread_system_return: LDR r0, =0x10000000 // Load PENDSVSET bit LDR r1, =0xE000ED04 // Load ICSR address STR r0, [r1] // 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 diff --git a/ports/cortex_m3/ac5/example_build/sample_threadx.c b/ports/cortex_m3/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m3/ac5/example_build/sample_threadx.c +++ b/ports/cortex_m3/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m3/ac5/inc/tx_port.h b/ports/cortex_m3/ac5/inc/tx_port.h index 32e640ba..51383750 100644 --- a/ports/cortex_m3/ac5/inc/tx_port.h +++ b/ports/cortex_m3/ac5/inc/tx_port.h @@ -699,7 +699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC5 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m3/ac6/inc/tx_port.h b/ports/cortex_m3/ac6/inc/tx_port.h index 0a25ae64..c90f1445 100644 --- a/ports/cortex_m3/ac6/inc/tx_port.h +++ b/ports/cortex_m3/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,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(); @@ -589,7 +592,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } - #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); @@ -699,7 +701,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 e1c5c2a2..a8654f6b 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m3/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 diff --git a/ports/cortex_m3/ghs/example_build/sample_threadx.c b/ports/cortex_m3/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m3/ghs/example_build/sample_threadx.c +++ b/ports/cortex_m3/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m3/ghs/inc/tx_port.h b/ports/cortex_m3/ghs/inc/tx_port.h index 1327b3a7..da8c1f3f 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GHS Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m3/gnu/example_build/sample_threadx.c b/ports/cortex_m3/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m3/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m3/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h index 23affb8b..41b48ad3 100644 --- a/ports/cortex_m3/gnu/inc/tx_port.h +++ b/ports/cortex_m3/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,7 +541,7 @@ 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 +554,6 @@ __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"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +579,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 +589,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -699,7 +702,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 9d9a32fc..92ad3f62 100644 --- a/ports/cortex_m3/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m3/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/cortex_m3/iar/example_build/sample_threadx.c b/ports/cortex_m3/iar/example_build/sample_threadx.c index a12160fa..3b1fcf42 100644 --- a/ports/cortex_m3/iar/example_build/sample_threadx.c +++ b/ports/cortex_m3/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m3/iar/inc/tx_port.h b/ports/cortex_m3/iar/inc/tx_port.h index ff8b75ca..deb37e74 100644 --- a/ports/cortex_m3/iar/inc/tx_port.h +++ b/ports/cortex_m3/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,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(); @@ -589,7 +592,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } - #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); @@ -699,7 +701,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 712a6e5c..8bd4ca82 100644 --- a/ports/cortex_m3/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m3/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 diff --git a/ports/cortex_m3/keil/example_build/sample_threadx.c b/ports/cortex_m3/keil/example_build/sample_threadx.c index 34453f42..2f0e2b98 100644 --- a/ports/cortex_m3/keil/example_build/sample_threadx.c +++ b/ports/cortex_m3/keil/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 six threads of different priorities, using a message queue, semaphore, and an event flags group. */ diff --git a/ports/cortex_m3/keil/inc/tx_port.h b/ports/cortex_m3/keil/inc/tx_port.h index 6ec876dc..8ed6e0d8 100644 --- a/ports/cortex_m3/keil/inc/tx_port.h +++ b/ports/cortex_m3/keil/inc/tx_port.h @@ -699,7 +699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/Keil Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c b/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c index cea22889..37233c9a 100644 --- a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c +++ b/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/cortex_m33/ac6/inc/tx_port.h b/ports/cortex_m33/ac6/inc/tx_port.h index e2a8f6e6..bb71cc55 100644 --- a/ports/cortex_m33/ac6/inc/tx_port.h +++ b/ports/cortex_m33/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +543,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 +556,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 +582,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(); @@ -613,7 +617,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 3c97b666..e57b28ea 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m33/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 diff --git a/ports/cortex_m33/gnu/example_build/sample_threadx.c b/ports/cortex_m33/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m33/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m33/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m33/gnu/inc/tx_port.h b/ports/cortex_m33/gnu/inc/tx_port.h index 727e9fce..c8b56cd7 100644 --- a/ports/cortex_m33/gnu/inc/tx_port.h +++ b/ports/cortex_m33/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +543,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) @@ -579,6 +581,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 +591,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -613,7 +617,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 17db56a5..15609393 100644 --- a/ports/cortex_m33/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m33/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/cortex_m33/iar/inc/tx_port.h b/ports/cortex_m33/iar/inc/tx_port.h index 62f20620..ced03711 100644 --- a/ports/cortex_m33/iar/inc/tx_port.h +++ b/ports/cortex_m33/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +543,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 +556,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 +582,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(); @@ -613,7 +617,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 442e0e14..83eb4a66 100644 --- a/ports/cortex_m33/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m33/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 diff --git a/ports/cortex_m4/ac5/example_build/sample_threadx.c b/ports/cortex_m4/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m4/ac5/example_build/sample_threadx.c +++ b/ports/cortex_m4/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m4/ac5/inc/tx_port.h b/ports/cortex_m4/ac5/inc/tx_port.h index 87b3dd5c..6e16ad45 100644 --- a/ports/cortex_m4/ac5/inc/tx_port.h +++ b/ports/cortex_m4/ac5/inc/tx_port.h @@ -699,7 +699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC5 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_m4/ac6/example_build/sample_threadx/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m4/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_m4/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index fa109c52..cf5bcb06 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,22 @@ 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(); +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(0); +#else + __enable_interrupts(); +#endif + __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(); @@ -699,7 +717,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 b4348f9d..4c5068ee 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m4/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 diff --git a/ports/cortex_m4/ghs/example_build/sample_threadx.c b/ports/cortex_m4/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m4/ghs/example_build/sample_threadx.c +++ b/ports/cortex_m4/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m4/ghs/inc/tx_port.h b/ports/cortex_m4/ghs/inc/tx_port.h index 4382845a..f2b66c76 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GHS Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m4/gnu/example_build/sample_threadx.c b/ports/cortex_m4/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m4/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m4/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h index 7c2b04c5..3f86a841 100644 --- a/ports/cortex_m4/gnu/inc/tx_port.h +++ b/ports/cortex_m4/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,9 +541,10 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -552,7 +555,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 +581,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 +591,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 8c4a09fd..4709af37 100644 --- a/ports/cortex_m4/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m4/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/cortex_m4/iar/example_build/sample_threadx.c b/ports/cortex_m4/iar/example_build/sample_threadx.c index 55b63731..a1b9cf03 100644 --- a/ports/cortex_m4/iar/example_build/sample_threadx.c +++ b/ports/cortex_m4/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/cortex_m4/iar/inc/tx_port.h b/ports/cortex_m4/iar/inc/tx_port.h index 1253befa..39de14f7 100644 --- a/ports/cortex_m4/iar/inc/tx_port.h +++ b/ports/cortex_m4/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,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(); @@ -589,7 +592,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } - #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); @@ -699,7 +701,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 4f8b9870..f9a668d9 100644 --- a/ports/cortex_m4/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m4/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 diff --git a/ports/cortex_m4/keil/example_build/demo_threadx.c b/ports/cortex_m4/keil/example_build/demo_threadx.c index 34453f42..2f0e2b98 100644 --- a/ports/cortex_m4/keil/example_build/demo_threadx.c +++ b/ports/cortex_m4/keil/example_build/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 six threads of different priorities, using a message queue, semaphore, and an event flags group. */ diff --git a/ports/cortex_m4/keil/inc/tx_port.h b/ports/cortex_m4/keil/inc/tx_port.h index f96d819e..3477ab04 100644 --- a/ports/cortex_m4/keil/inc/tx_port.h +++ b/ports/cortex_m4/keil/inc/tx_port.h @@ -699,7 +699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/Keil Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c b/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c index cea22889..37233c9a 100644 --- a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c +++ b/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/cortex_m55/ac6/inc/tx_port.h b/ports/cortex_m55/ac6/inc/tx_port.h index 9d11a04b..86e5410e 100644 --- a/ports/cortex_m55/ac6/inc/tx_port.h +++ b/ports/cortex_m55/ac6/inc/tx_port.h @@ -613,7 +613,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m55/gnu/example_build/sample_threadx.c b/ports/cortex_m55/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m55/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m55/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m55/gnu/inc/tx_port.h b/ports/cortex_m55/gnu/inc/tx_port.h index a70426fa..77e9105f 100644 --- a/ports/cortex_m55/gnu/inc/tx_port.h +++ b/ports/cortex_m55/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +543,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 +556,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 +582,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 +592,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -613,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 0fc717b9..f13f832a 100644 --- a/ports/cortex_m55/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m55/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/cortex_m55/iar/inc/tx_port.h b/ports/cortex_m55/iar/inc/tx_port.h index b8a389f5..e10e7634 100644 --- a/ports/cortex_m55/iar/inc/tx_port.h +++ b/ports/cortex_m55/iar/inc/tx_port.h @@ -579,6 +579,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(); @@ -613,7 +614,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 2762f49e..20493afc 100644 --- a/ports/cortex_m55/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m55/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 diff --git a/ports/cortex_m7/ac5/example_build/sample_threadx.c b/ports/cortex_m7/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m7/ac5/example_build/sample_threadx.c +++ b/ports/cortex_m7/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m7/ac5/inc/tx_port.h b/ports/cortex_m7/ac5/inc/tx_port.h index 717bd127..2bf1d33d 100644 --- a/ports/cortex_m7/ac5/inc/tx_port.h +++ b/ports/cortex_m7/ac5/inc/tx_port.h @@ -699,7 +699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC5 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m7/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_m7/ac6/example_build/sample_threadx/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m7/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_m7/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m7/ac6/inc/tx_port.h b/ports/cortex_m7/ac6/inc/tx_port.h index d3b3bb01..5a271fe6 100644 --- a/ports/cortex_m7/ac6/inc/tx_port.h +++ b/ports/cortex_m7/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,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(); @@ -589,7 +592,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } - #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); @@ -699,7 +701,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 831c00e4..a092e34c 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m7/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 diff --git a/ports/cortex_m7/ghs/example_build/sample_threadx.c b/ports/cortex_m7/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_m7/ghs/example_build/sample_threadx.c +++ b/ports/cortex_m7/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m7/ghs/inc/tx_port.h b/ports/cortex_m7/ghs/inc/tx_port.h index aabf714e..7b1480fa 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GHS Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m7/gnu/example_build/sample_threadx.c b/ports/cortex_m7/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m7/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m7/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h index 48a34cfa..824d60d9 100644 --- a/ports/cortex_m7/gnu/inc/tx_port.h +++ b/ports/cortex_m7/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,25 +541,26 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 } + __attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void) { unsigned int int_posture; @@ -578,6 +581,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 +591,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -699,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 ce5a3f46..180894b3 100644 --- a/ports/cortex_m7/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m7/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/cortex_m7/iar/example_build/sample_threadx.c b/ports/cortex_m7/iar/example_build/sample_threadx.c index f1f4cb87..4ad474a1 100644 --- a/ports/cortex_m7/iar/example_build/sample_threadx.c +++ b/ports/cortex_m7/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/cortex_m7/iar/inc/tx_port.h b/ports/cortex_m7/iar/inc/tx_port.h index 63d821bf..30af8b42 100644 --- a/ports/cortex_m7/iar/inc/tx_port.h +++ b/ports/cortex_m7/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -539,20 +541,20 @@ 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 +#endif + __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); } -#endif __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture) { #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 +580,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(); @@ -589,7 +592,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } - #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); @@ -699,7 +701,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 0cef80c6..00a07ea8 100644 --- a/ports/cortex_m7/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m7/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 diff --git a/ports/cortex_m85/ac6/inc/tx_port.h b/ports/cortex_m85/ac6/inc/tx_port.h index 7e119fee..854619d7 100644 --- a/ports/cortex_m85/ac6/inc/tx_port.h +++ b/ports/cortex_m85/ac6/inc/tx_port.h @@ -613,7 +613,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/AC6 Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m85/gnu/example_build/sample_threadx.c b/ports/cortex_m85/gnu/example_build/sample_threadx.c index 13ffadba..b2fe3c89 100644 --- a/ports/cortex_m85/gnu/example_build/sample_threadx.c +++ b/ports/cortex_m85/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_m85/gnu/inc/tx_port.h b/ports/cortex_m85/gnu/inc/tx_port.h index 9057a132..ce3a4cbe 100644 --- a/ports/cortex_m85/gnu/inc/tx_port.h +++ b/ports/cortex_m85/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +543,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 +556,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 +582,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 +592,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -613,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/GNU Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; 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 bbb5a630..35630094 100644 --- a/ports/cortex_m85/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m85/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/cortex_m85/iar/inc/tx_port.h b/ports/cortex_m85/iar/inc/tx_port.h index bf245049..33cf512d 100644 --- a/ports/cortex_m85/iar/inc/tx_port.h +++ b/ports/cortex_m85/iar/inc/tx_port.h @@ -541,7 +541,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 +554,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 @@ -613,7 +614,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; @@ -623,3 +624,5 @@ 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 768262a2..fcc87228 100644 --- a/ports/cortex_m85/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m85/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 diff --git a/ports/cortex_r4/ac5/example_build/sample_threadx.c b/ports/cortex_r4/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r4/ac5/example_build/sample_threadx.c +++ b/ports/cortex_r4/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r4/ac5/inc/tx_port.h b/ports/cortex_r4/ac5/inc/tx_port.h index 07233290..7db943d4 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/ac6/example_build/sample_threadx/gic.c b/ports/cortex_r4/ac6/example_build/sample_threadx/gic.c index 32f21bbe..954d4fcd 100644 --- a/ports/cortex_r4/ac6/example_build/sample_threadx/gic.c +++ b/ports/cortex_r4/ac6/example_build/sample_threadx/gic.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + /** GIC start **/ /* ------------------------- Interrupt Number Definition ------------------------ */ diff --git a/ports/cortex_r4/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_r4/ac6/example_build/sample_threadx/sample_threadx.c index 6a996f77..05ad809b 100644 --- a/ports/cortex_r4/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_r4/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r4/ac6/example_build/sample_threadx/timer.c b/ports/cortex_r4/ac6/example_build/sample_threadx/timer.c index e964d0f6..c71cab98 100644 --- a/ports/cortex_r4/ac6/example_build/sample_threadx/timer.c +++ b/ports/cortex_r4/ac6/example_build/sample_threadx/timer.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + #include "gic.h" /* Systick registers */ diff --git a/ports/cortex_r4/ac6/example_build/sample_threadx/timer.h b/ports/cortex_r4/ac6/example_build/sample_threadx/timer.h index efab1fe1..6bb3b238 100644 --- a/ports/cortex_r4/ac6/example_build/sample_threadx/timer.h +++ b/ports/cortex_r4/ac6/example_build/sample_threadx/timer.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + #ifndef TIMER_H #define TIMER_H void timer_init(); diff --git a/ports/cortex_r4/ac6/inc/tx_port.h b/ports/cortex_r4/ac6/inc/tx_port.h index ff4ed9d1..5aa6919b 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC6 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/ghs/example_build/sample_threadx.c b/ports/cortex_r4/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r4/ghs/example_build/sample_threadx.c +++ b/ports/cortex_r4/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r4/ghs/inc/tx_port.h b/ports/cortex_r4/ghs/inc/tx_port.h index 22daf8ea..1e9933ad 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/gnu/example_build/sample_threadx.c b/ports/cortex_r4/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r4/gnu/example_build/sample_threadx.c +++ b/ports/cortex_r4/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r4/gnu/inc/tx_port.h b/ports/cortex_r4/gnu/inc/tx_port.h index 827590c9..7b292056 100644 --- a/ports/cortex_r4/gnu/inc/tx_port.h +++ b/ports/cortex_r4/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 Cortex-R4/GNU Version 6.5.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/iar/example_build/sample_threadx.c b/ports/cortex_r4/iar/example_build/sample_threadx.c index ca92ff86..52496767 100644 --- a/ports/cortex_r4/iar/example_build/sample_threadx.c +++ b/ports/cortex_r4/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r4/iar/inc/tx_port.h b/ports/cortex_r4/iar/inc/tx_port.h index c2950326..4696023b 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_r5/ac5/example_build/sample_threadx.c b/ports/cortex_r5/ac5/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r5/ac5/example_build/sample_threadx.c +++ b/ports/cortex_r5/ac5/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r5/ac5/inc/tx_port.h b/ports/cortex_r5/ac5/inc/tx_port.h index aa188c5c..c643d818 100644 --- a/ports/cortex_r5/ac5/inc/tx_port.h +++ b/ports/cortex_r5/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 Cortex-R5/AC5 Version 6.5.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC5 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_r5/ac6/example_build/sample_threadx/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r5/ac6/example_build/sample_threadx/sample_threadx.c +++ b/ports/cortex_r5/ac6/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r5/ac6/inc/tx_port.h b/ports/cortex_r5/ac6/inc/tx_port.h index 360e3178..d25f5970 100644 --- a/ports/cortex_r5/ac6/inc/tx_port.h +++ b/ports/cortex_r5/ac6/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 Cortex-R5/AC6 Version 6.5.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC6 Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/ghs/example_build/sample_threadx.c b/ports/cortex_r5/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r5/ghs/example_build/sample_threadx.c +++ b/ports/cortex_r5/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r5/ghs/inc/tx_port.h b/ports/cortex_r5/ghs/inc/tx_port.h index 5b435fcb..542dca9a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/gnu/example_build/sample_threadx.c b/ports/cortex_r5/gnu/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r5/gnu/example_build/sample_threadx.c +++ b/ports/cortex_r5/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r5/gnu/inc/tx_port.h b/ports/cortex_r5/gnu/inc/tx_port.h index 0a09f9ea..28716e93 100644 --- a/ports/cortex_r5/gnu/inc/tx_port.h +++ b/ports/cortex_r5/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 Cortex-R5/GNU Version 6.5.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/iar/example_build/sample_threadx.c b/ports/cortex_r5/iar/example_build/sample_threadx.c index ca92ff86..52496767 100644 --- a/ports/cortex_r5/iar/example_build/sample_threadx.c +++ b/ports/cortex_r5/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r5/iar/inc/tx_port.h b/ports/cortex_r5/iar/inc/tx_port.h index eb5e46d9..31074a1f 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/IAR Version 6.5.1.202602 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_r7/ghs/example_build/sample_threadx.c b/ports/cortex_r7/ghs/example_build/sample_threadx.c index 8c61de06..6cf3e72a 100644 --- a/ports/cortex_r7/ghs/example_build/sample_threadx.c +++ b/ports/cortex_r7/ghs/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/cortex_r7/ghs/inc/tx_port.h b/ports/cortex_r7/ghs/inc/tx_port.h index 11e05937..0c5ccd2b 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R7/Green Hills Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/linux/gnu/example_build/sample_threadx.c b/ports/linux/gnu/example_build/sample_threadx.c index 43c0bdd4..99fd42a4 100644 --- a/ports/linux/gnu/example_build/sample_threadx.c +++ b/ports/linux/gnu/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h index 83d72df0..40f5d505 100644 --- a/ports/linux/gnu/inc/tx_port.h +++ b/ports/linux/gnu/inc/tx_port.h @@ -533,7 +533,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.0.202601 *"; + "Copyright (c) Microsoft Corporation * ThreadX Linux/gcc Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/risc-v32/clang/CMakeLists.txt b/ports/risc-v32/clang/CMakeLists.txt index 9b725103..beaa31aa 100644 --- a/ports/risc-v32/clang/CMakeLists.txt +++ b/ports/risc-v32/clang/CMakeLists.txt @@ -1,19 +1,11 @@ +# RISC-V32 Clang port. +# +# Clang and GNU use identical RISC-V assembly sources; this port +# compiles from gnu/src/ so fixes and features are shared automatically. +include(${CMAKE_CURRENT_LIST_DIR}/../../../cmake/threadx_riscv_port.cmake) -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_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 +threadx_add_riscv_port( + SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/../gnu/src + INC_DIR ${CMAKE_CURRENT_LIST_DIR}/inc + EXAMPLE_DIR ${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt ) diff --git a/ports/risc-v32/clang/example_build/qemu_virt/build_libthreadx.sh b/ports/risc-v32/clang/example_build/qemu_virt/build_libthreadx.sh index ff84c974..4d3695e4 100755 --- a/ports/risc-v32/clang/example_build/qemu_virt/build_libthreadx.sh +++ b/ports/risc-v32/clang/example_build/qemu_virt/build_libthreadx.sh @@ -1,4 +1,15 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + pushd ../../../../../ #cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_clang.cmake . diff --git a/ports/risc-v32/clang/example_build/qemu_virt/build_threadx_sample.sh b/ports/risc-v32/clang/example_build/qemu_virt/build_threadx_sample.sh index a1b3cb88..d774ca9c 100755 --- a/ports/risc-v32/clang/example_build/qemu_virt/build_threadx_sample.sh +++ b/ports/risc-v32/clang/example_build/qemu_virt/build_threadx_sample.sh @@ -1,4 +1,15 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + DIRNAME=$(dirname "$0") BASEDIR=$DIRNAME/../../../../.. @@ -8,7 +19,7 @@ mkdir -p build CC=clang-18 LD=ld.lld-18 -$CC -I $BASEDIR/ports/risc-v32/clang/inc -I $BASEDIR/build/custom_inc -g --sysroot=/opt/riscv_rv32ima/riscv32-unknown-elf --target=riscv32 -march=rv32ima_zicsr -mabi=ilp32 -o build/entry.obj -c entry.s +$CC -I $BASEDIR/ports/risc-v32/clang/inc -I $BASEDIR/build/custom_inc -g --sysroot=/opt/riscv_rv32ima/riscv32-unknown-elf --target=riscv32 -march=rv32ima_zicsr -mabi=ilp32 -o build/entry.obj -c entry.S $CC -DTX_INCLUDE_USER_DEFINE_FILE -I $BASEDIR/ports/risc-v32/clang/inc -I $BASEDIR/build/custom_inc -isystem $BASEDIR/common/inc -g --sysroot=/opt/riscv_rv32ima/riscv32-unknown-elf --target=riscv32 -march=rv32ima_zicsr -mabi=ilp32 -D__ASSEMBLER__ -o build/tx_initialize_low_level.obj -c tx_initialize_low_level.S $CC -DTX_INCLUDE_USER_DEFINE_FILE -I $BASEDIR/ports/risc-v32/clang/inc -I $BASEDIR/build/custom_inc -isystem $BASEDIR/common/inc -g --sysroot=/opt/riscv_rv32ima/riscv32-unknown-elf --target=riscv32 -march=rv32ima_zicsr -mabi=ilp32 -o build/board.obj -c board.c $CC -DTX_INCLUDE_USER_DEFINE_FILE -I $BASEDIR/ports/risc-v32/clang/inc -I $BASEDIR/build/custom_inc -isystem $BASEDIR/common/inc -g --sysroot=/opt/riscv_rv32ima/riscv32-unknown-elf --target=riscv32 -march=rv32ima_zicsr -mabi=ilp32 -o build/hwtimer.obj -c hwtimer.c diff --git a/ports/risc-v32/clang/example_build/qemu_virt/csr.h b/ports/risc-v32/clang/example_build/qemu_virt/csr.h index ab335dcc..b5df6f12 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/csr.h +++ b/ports/risc-v32/clang/example_build/qemu_virt/csr.h @@ -1,343 +1 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This program and the accompanying materials are made available under the - * terms of the MIT License which is available at - * https://opensource.org/licenses/MIT. - * - * SPDX-License-Identifier: MIT - **************************************************************************/ - - -#ifndef RISCV_CSR_H -#define RISCV_CSR_H - - -// Machine Status Register, mstatus -#define MSTATUS_MPP_MASK (3L << 11) // previous mode. -#define MSTATUS_MPP_M (3L << 11) -#define MSTATUS_MPP_S (1L << 11) -#define MSTATUS_MPP_U (0L << 11) -#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. -#define MSTATUS_MPIE (1L << 7) -#define MSTATUS_FS (1L << 13) - -// Machine-mode Interrupt Enable -#define MIE_MTIE (1L << 7) -#define MIE_MSIE (1L << 3) -#define MIE_MEIE (1L << 11) -#define MIE_STIE (1L << 5) // supervisor timer -#define MIE_SSIE (1L << 1) -#define MIE_SEIE (1L << 9) - -// Supervisor Status Register, sstatus -#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User -#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable -#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable -#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable -#define SSTATUS_UIE (1L << 0) // User Interrupt Enable -#define SSTATUS_SPIE (1L << 5) -#define SSTATUS_UPIE (1L << 4) - -// Supervisor Interrupt Enable -#define SIE_SEIE (1L << 9) // external -#define SIE_STIE (1L << 5) // timer -#define SIE_SSIE (1L << 1) // software - -#ifndef __ASSEMBLER__ - -#include <stdint.h> - -static inline uint32_t riscv_get_core() -{ - uint32_t x; - asm volatile("csrr %0, mhartid" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_mstatus() -{ - uint32_t x; - asm volatile("csrr %0, mstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mstatus(uint32_t x) -{ - asm volatile("csrw mstatus, %0" : : "r" (x)); -} - -static inline void riscv_writ_mepc(uint32_t x) -{ - asm volatile("csrw mepc, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sstatus() -{ - uint32_t x; - asm volatile("csrr %0, sstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sstatus(uint32_t x) -{ - asm volatile("csrw sstatus, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sip() -{ - uint32_t x; - asm volatile("csrr %0, sip" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sip(uint32_t x) -{ - asm volatile("csrw sip, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sie() -{ - uint32_t x; - asm volatile("csrr %0, sie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sie(uint32_t x) -{ - asm volatile("csrw sie, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mie() -{ - uint32_t x; - asm volatile("csrr %0, mie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mie(uint32_t x) -{ - asm volatile("csrw mie, %0" : : "r" (x)); -} - -static inline void riscv_writ_sepc(uint32_t x) -{ - asm volatile("csrw sepc, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sepc() -{ - uint32_t x; - asm volatile("csrr %0, sepc" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_medeleg() -{ - uint32_t x; - asm volatile("csrr %0, medeleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_medeleg(uint32_t x) -{ - asm volatile("csrw medeleg, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mideleg() -{ - uint32_t x; - asm volatile("csrr %0, mideleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mideleg(uint32_t x) -{ - asm volatile("csrw mideleg, %0" : : "r" (x)); -} - -static inline void riscv_writ_stvec(uint32_t x) -{ - asm volatile("csrw stvec, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_stvec() -{ - uint32_t x; - asm volatile("csrr %0, stvec" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_stimecmp() -{ - uint32_t x; - asm volatile("csrr %0, 0x14d" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_stimecmp(uint32_t x) -{ - asm volatile("csrw 0x14d, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_menvcfg() -{ - uint32_t x; - asm volatile("csrr %0, 0x30a" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_menvcfg(uint32_t x) -{ - asm volatile("csrw 0x30a, %0" : : "r" (x)); -} - -static inline void riscv_writ_pmpcfg0(uint32_t x) -{ - asm volatile("csrw pmpcfg0, %0" : : "r" (x)); -} - -static inline void riscv_writ_pmpaddr0(uint32_t x) -{ - asm volatile("csrw pmpaddr0, %0" : : "r" (x)); -} - -static inline void riscv_writ_satp(uint32_t x) -{ - asm volatile("csrw satp, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_satp() -{ - uint32_t x; - asm volatile("csrr %0, satp" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_scause() -{ - uint32_t x; - asm volatile("csrr %0, scause" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_stval() -{ - uint32_t x; - asm volatile("csrr %0, stval" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mcounteren(uint32_t x) -{ - asm volatile("csrw mcounteren, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mcounteren() -{ - uint32_t x; - asm volatile("csrr %0, mcounteren" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_time() -{ - uint32_t x; - asm volatile("csrr %0, time" : "=r" (x) ); - return x; -} - -static inline void riscv_sintr_on() -{ - uint32_t sstatus = riscv_get_sstatus(); - sstatus |= SSTATUS_SIE; - riscv_writ_sstatus(sstatus); -} - -static inline void riscv_sintr_off() -{ - uint32_t sstatus = riscv_get_sstatus(); - sstatus &= (~SSTATUS_SIE); - riscv_writ_sstatus(sstatus); -} - -static inline int riscv_sintr_get() -{ - uint32_t x = riscv_get_sstatus(); - return (x & SSTATUS_SIE) != 0; -} - -static inline void riscv_sintr_restore(int x) -{ - if(x) - riscv_sintr_on(); - else - riscv_sintr_off(); -} - -static inline void riscv_mintr_on() -{ - uint32_t mstatus = riscv_get_mstatus(); - mstatus |= MSTATUS_MIE; - riscv_writ_mstatus(mstatus); -} - -static inline void riscv_mintr_off() -{ - uint32_t mstatus = riscv_get_mstatus(); - mstatus &= (~MSTATUS_MIE); - riscv_writ_mstatus(mstatus); -} - -static inline int riscv_mintr_get() -{ - uint32_t x = riscv_get_mstatus(); - return (x & MSTATUS_MIE) != 0; -} - -static inline void riscv_mintr_restore(int x) -{ - if(x) - riscv_mintr_on(); - else - riscv_mintr_off(); -} - -static inline uint32_t riscv_get_sp() -{ - uint32_t x; - asm volatile("mv %0, sp" : "=r" (x) ); - return x; -} - -// read and write tp, the thread pointer, which xv6 uses to hold -// this core's hartid (core number), the index into cpus[]. -static inline uint32_t riscv_get_tp() -{ - uint32_t x; - asm volatile("mv %0, tp" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_tp(uint32_t x) -{ - asm volatile("mv tp, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_ra() -{ - uint32_t x; - asm volatile("mv %0, ra" : "=r" (x) ); - return x; -} - -// flush the TLB. -static inline void sfence_vma() -{ - // the zero, zero means flush all TLB entries. - asm volatile("sfence.vma zero, zero"); -} - -#endif // __ASSEMBLER__ - -#endif +../../../../risc-v_common/inc/csr.h
\ No newline at end of file diff --git a/ports/risc-v32/clang/example_build/qemu_virt/demo_threadx.c b/ports/risc-v32/clang/example_build/qemu_virt/demo_threadx.c index a5955b29..449b397b 100644 --- a/ports/risc-v32/clang/example_build/qemu_virt/demo_threadx.c +++ b/ports/risc-v32/clang/example_build/qemu_virt/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/risc-v32/clang/example_build/qemu_virt/entry.S b/ports/risc-v32/clang/example_build/qemu_virt/entry.S new file mode 100644 index 00000000..f9645bc7 --- /dev/null +++ b/ports/risc-v32/clang/example_build/qemu_virt/entry.S @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + + +.section .text +.align 4 +.global _start +.extern main +.extern _sysstack_start +.extern _bss_start +.extern _bss_end +_start: + csrr t0, mhartid + bne t0, zero, 1f + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + la t0, _sysstack_start + li t1, 0x1000 + add sp, t0, t1 + la t0, _bss_start + la t1, _bss_end +_bss_clean_start: + bgeu t0, t1, _bss_clean_end + sb zero, 0(t0) + addi t0, t0, 1 + j _bss_clean_start +_bss_clean_end: + call main +1: + /* todo smp */ + wfi + j 1b diff --git a/ports/risc-v32/clang/example_build/qemu_virt/entry.s b/ports/risc-v32/clang/example_build/qemu_virt/entry.s deleted file mode 100644 index 9b202ca1..00000000 --- a/ports/risc-v32/clang/example_build/qemu_virt/entry.s +++ /dev/null @@ -1,58 +0,0 @@ - -.section .text -.align 4 -.global _start -.extern main -.extern _sysstack_start -.extern _bss_start -.extern _bss_end -_start: - csrr t0, mhartid - bne t0, zero, 1f - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10, 0 - li x11, 0 - li x12, 0 - li x13, 0 - li x14, 0 - li x15, 0 - li x16, 0 - li x17, 0 - li x18, 0 - li x19, 0 - li x20, 0 - li x21, 0 - li x22, 0 - li x23, 0 - li x24, 0 - li x25, 0 - li x26, 0 - li x27, 0 - li x28, 0 - li x29, 0 - li x30, 0 - li x31, 0 - la t0, _sysstack_start - li t1, 0x1000 - add sp, t0, t1 - la t0, _bss_start - la t1, _bss_end -_bss_clean_start: - bgeu t0, t1, _bss_clean_end - sb zero, 0(t0) - addi t0, t0, 1 - j _bss_clean_start -_bss_clean_end: - call main -1: - /* todo smp */ - wfi - j 1b diff --git a/ports/risc-v32/clang/example_build/qemu_virt/plic.c b/ports/risc-v32/clang/example_build/qemu_virt/plic.c index 01e5c71a..b247f4fe 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/plic.c +++ b/ports/risc-v32/clang/example_build/qemu_virt/plic.c @@ -1,72 +1 @@ -#include "plic.h" -#include <stddef.h> -irq_callback callbacks[MAX_CALLBACK_NUM]; - -void plic_irq_enable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno)); - return; -} - -void plic_irq_disable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno))); - return; -} - -void plic_prio_set(int irqno, int prio) -{ - PLIC_SET_PRIO(irqno, prio); -} - -int plic_prio_get(int irqno) -{ - return PLIC_GET_PRIO(irqno); -} - -int plic_register_callback(int irqno, irq_callback callback) -{ - if(!(irqno >=0 && irqno < MAX_CALLBACK_NUM)) - return -1; - callbacks[irqno] = callback; - return 0; -} - -int plic_unregister_callback(int irqno) -{ - return plic_register_callback(irqno, NULL); -} - -int plic_init(void) -{ - for(int i=0;i<MAX_CALLBACK_NUM;i++) - { - callbacks[i] = NULL; - } - return 0; -} - -int plic_claim(void) -{ - int hart = riscv_get_core(); - return (*(uint32_t*)PLIC_MCLAIM(hart)); -} - -void plic_complete(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; - return; -} - -int plic_irq_intr(void) -{ - int ret = -1; - int irqno = plic_claim(); - if(callbacks[irqno] != NULL) - ret = (callbacks[irqno])(irqno); - plic_complete(irqno); - return ret; -} +../../../../risc-v_common/example_build/plic/plic.c
\ No newline at end of file diff --git a/ports/risc-v32/clang/example_build/qemu_virt/plic.h b/ports/risc-v32/clang/example_build/qemu_virt/plic.h index 899bfb90..f776a3d2 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/plic.h +++ b/ports/risc-v32/clang/example_build/qemu_virt/plic.h @@ -1,49 +1 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This program and the accompanying materials are made available under the - * terms of the MIT License which is available at - * https://opensource.org/licenses/MIT. - * - * SPDX-License-Identifier: MIT - **************************************************************************/ - -#ifndef RISCV_PLIC_H -#define RISCV_PLIC_H - -#include "csr.h" -#include <stdint.h> - -#define PLIC 0x0c000000L -#define PLIC_PRIORITY (PLIC + 0x0) -#define PLIC_PENDING (PLIC + 0x1000) -#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100) -#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100) -#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000) -#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000) -#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000) -#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000) -#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 MAX_CALLBACK_NUM 128 -typedef int (*irq_callback)(int irqno); - -void plic_irq_enable(int irqno); -void plic_irq_disable(int irqno); -int plic_prio_get(int irqno); -void plic_prio_set(int irqno, int prio); -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 - +../../../../risc-v_common/example_build/plic/plic.h
\ No newline at end of file diff --git a/ports/risc-v32/clang/example_build/qemu_virt/trap.c b/ports/risc-v32/clang/example_build/qemu_virt/trap.c index a2733e02..bdce3305 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/trap.c +++ b/ports/risc-v32/clang/example_build/qemu_virt/trap.c @@ -1,67 +1 @@ -#include "csr.h" -#include <stdint.h> -#include "uart.h" -#include "hwtimer.h" -#include "plic.h" -#include <tx_port.h> -#include <tx_api.h> - -#define OS_IS_INTERUPT(mcause) (mcause & 0x80000000u) -#define OS_IS_EXCEPTION(mcause) (~(OS_IS_INTERUPT)) -#define OS_IS_TICK_INT(mcause) (mcause == 0x80000007u) -#define OS_IS_SOFT_INT(mcause) (mcause == 0x80000003u) -#define OS_IS_EXT_INT(mcause) (mcause == 0x8000000bu) -#define OS_IS_TRAP_USER(mcause) (mcause == 0x0000000bu) -extern void _tx_timer_interrupt(void); - -extern int uart_putc(int ch); - -static void print_hex(uintptr_t val) -{ - char digits[] = "0123456789ABCDEF"; - uart_putc('0'); - uart_putc('x'); - for(int i = (sizeof(uintptr_t)*2) - 1; i >= 0; i--) { - int d = (val >> (i*4)) & 0xF; - uart_putc(digits[d]); - } - uart_putc('\n'); -} - -void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) -{ - // uart_puts("DEBUG : threadx/ports/risc-v32/gnu/example_build/qemu_virt/trap.c, trap_handler\n"); - if(OS_IS_INTERUPT(mcause)) - { - if(OS_IS_TICK_INT(mcause)) - { - hwtimer_handler(); - _tx_timer_interrupt(); - } - else if(OS_IS_EXT_INT(mcause)) - { - int ret = plic_irq_intr(); - if(ret) - { - puts("[INTERRUPT]: handler irq error!"); - while(1) ; - } - } - else - { - puts("[INTERRUPT]: now can't deal with the interrupt!"); - while(1) ; - } - } - else - { - puts("[EXCEPTION] : Unkown Error!!"); - puts("mcause:"); - print_hex(mcause); - puts("mepc:"); - print_hex(mepc); - puts("mtval:"); - print_hex(mtval); - while(1) ; - } -} +../../../../risc-v_common/example_build/trap/trap_qemu.c
\ No newline at end of file diff --git a/ports/risc-v32/clang/example_build/qemu_virt/uart.c b/ports/risc-v32/clang/example_build/qemu_virt/uart.c index a175b7d2..1666c8c8 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/uart.c +++ b/ports/risc-v32/clang/example_build/qemu_virt/uart.c @@ -1,102 +1 @@ -#include "uart.h" -#include "csr.h" -#include "plic.h" -#include <stdint.h> - -// the UART control registers are memory-mapped -// at address UART0. this macro returns the -// address of one of the registers. -#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg))) - -// the UART control registers. -// some have different meanings for -// read vs write. -// see http://byterunner.com/16550.html -#define RHR 0 // receive holding register (for input bytes) -#define THR 0 // transmit holding register (for output bytes) -#define IER 1 // interrupt enable register -#define IER_RX_ENABLE (1<<0) -#define IER_TX_ENABLE (1<<1) -#define FCR 2 // FIFO control register -#define FCR_FIFO_ENABLE (1<<0) -#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs -#define ISR 2 // interrupt status register -#define LCR 3 // line control register -#define LCR_EIGHT_BITS (3<<0) -#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate -#define LSR 5 // line status register -#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR -#define LSR_TX_IDLE (1<<5) // THR can accept another character to send - -#define ReadReg(reg) (*(Reg(reg))) -#define WriteReg(reg, v) (*(Reg(reg)) = (v)) - -int uart_init(void) -{ - // disable interrupts. - WriteReg(IER, 0x00); - - // special mode to set baud rate. - WriteReg(LCR, LCR_BAUD_LATCH); - - // LSB for baud rate of 38.4K. - WriteReg(0, 0x03); - - // MSB for baud rate of 38.4K. - WriteReg(1, 0x00); - - // leave set-baud mode, - // and set word length to 8 bits, no parity. - WriteReg(LCR, LCR_EIGHT_BITS); - - // reset and enable FIFOs. - WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); - - // enable transmit and receive interrupts. - // WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE); - - //enable UART0 in PLIC - plic_irq_enable(UART0_IRQ); - - //set UART0 priority in PLIC - plic_prio_set(UART0_IRQ, 1); - - //register callback for UART0 - //plic_register_callback(UART0_IRQ, uart_intr); - puts("[UART0] : Uart Init Done, this is Test output!"); - return 0; -} - -void uart_putc_nolock(int ch) -{ - // wait for Transmit Holding Empty to be set in LSR. - while((ReadReg(LSR) & LSR_TX_IDLE) == 0) - ; - WriteReg(THR, ch); - return; -} - -int uart_putc(int ch) -{ - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - uart_putc_nolock(ch); - riscv_mintr_restore(intr_enable); - return 1; -} - -int uart_puts(const char* str) -{ - int i; - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - for(i=0;str[i]!=0;i++) - { - uart_putc_nolock(str[i]); - } - uart_putc_nolock('\n'); - riscv_mintr_restore(intr_enable); - return i; -} - - +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.c
\ No newline at end of file diff --git a/ports/risc-v32/clang/example_build/qemu_virt/uart.h b/ports/risc-v32/clang/example_build/qemu_virt/uart.h index debfd9df..aba5ae7b 100644..120000 --- a/ports/risc-v32/clang/example_build/qemu_virt/uart.h +++ b/ports/risc-v32/clang/example_build/qemu_virt/uart.h @@ -1,23 +1 @@ -/*************************************************************************** - * 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 - **************************************************************************/ - -#ifndef RISCV_UART_H -#define RISCV_UART_H - -#define UART0 0x10000000L -#define UART0_IRQ 10 - -#define puts uart_puts -int uart_init(void); -int uart_putc(int ch); -void uart_putc_nolock(int ch); -int uart_puts(const char* str); -#endif +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.h
\ No newline at end of file diff --git a/ports/risc-v32/clang/inc/tx_port.h b/ports/risc-v32/clang/inc/tx_port.h index f89c148c..72b5e79c 100644 --- a/ports/risc-v32/clang/inc/tx_port.h +++ b/ports/risc-v32/clang/inc/tx_port.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2025 Quintauris + * Copyright (c) 2026 Quintauris * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -24,7 +24,7 @@ /* */ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ -/* tx_port.h RISC-V32/GNU */ +/* tx_port.h RISC-V32/Clang */ /* 6.4.x */ /* */ /* AUTHOR */ @@ -47,228 +47,8 @@ #ifndef TX_PORT_H #define TX_PORT_H -#ifndef __ASSEMBLER__ - -/* Include for memset. */ -#include <string.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 */ - -#endif /* __ASSEMBLER__ */ - - -/* Define ThreadX basic types for this port. */ - -#define VOID void - -#ifndef __ASSEMBLER__ -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 -#endif /* __ASSEMBLER__ */ - - - - -/* 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 1024 /* 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 RISC-V port. */ - -#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ -#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */ - - -/* 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. */ - -#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. */ - -#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. */ - -#define TX_THREAD_EXTENSION_0 -#define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 -#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 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 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. */ - -/* Expose helper used to perform an atomic read/modify/write of mstatus. - The helper composes and returns the posture per ThreadX contract. */ -#ifndef __ASSEMBLER__ -UINT _tx_thread_interrupt_control(UINT new_posture); -#endif - -#ifdef TX_DISABLE_INLINE - -#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; - -#define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory"); -#define TX_RESTORE { \ - unsigned long _temp_mstatus; \ - __asm__ volatile( \ - "csrc mstatus, 8\n" \ - "andi %0, %1, 8\n" \ - "csrs mstatus, %0" \ - : "=&r" (_temp_mstatus) \ - : "r" (interrupt_save) \ - : "memory"); \ - } - -#else - -#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; - -#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); -#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); - -#endif /* TX_DISABLE_INLINE */ - - -/* 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 +/* Include shared RISC-V32 port definitions common to all toolchain ports. */ +#include "../../common/tx_port_riscv32_common.h" /* Define the version ID of ThreadX. This may be utilized by the application. */ @@ -276,10 +56,10 @@ UINT _tx_thread_interrupt_control(UIN #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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ #endif /* __ASSEMBLER__ */ -#endif /* TX_PORT_H */
\ No newline at end of file +#endif /* TX_PORT_H */ diff --git a/ports/risc-v32/clang/src/tx_thread_context_restore.S b/ports/risc-v32/clang/src/tx_thread_context_restore.S deleted file mode 100644 index 88ac0ce3..00000000 --- a/ports/risc-v32/clang/src/tx_thread_context_restore.S +++ /dev/null @@ -1,410 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2025 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - .section .text -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_thread_context_restore RISC-V32/GNU */ -/* 6.4.x */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* 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 -_tx_thread_context_restore: - - /* Lockout interrupts. */ - - csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) - -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_exit // Call the ISR execution exit function -#endif - - /* Determine if interrupts are nested. */ - /* if (--_tx_thread_system_state) - { */ - - la t0, _tx_thread_system_state // Pickup addr of nested interrupt count - lw t1, 0(t0) // Pickup nested interrupt count - addi t1, t1, -1 // Decrement the nested interrupt counter - sw t1, 0(t0) // Store new nested count - beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore - - /* Interrupts are nested. */ - - /* Just recover the saved registers and return to the point of - interrupt. */ - - /* Recover floating point registers. */ -#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 - csrw fcsr, t0 // Restore fcsr -#endif - - /* Recover standard registers. */ - - /* Restore registers, - Skip global pointer because that does not change. - Also skip the saved registers since they have been restored by any function we called, - except s0 since we use it ourselves. */ - - lw t0, 30*4(sp) // Recover mepc - csrw mepc, t0 // Setup mepc - - /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. - Set MPIE and restore MPP to Machine, preserve other fields. */ - - csrr t1, mstatus - - /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */ - - li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode (bits 12:11) - - /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, - preserve everything except the bits we will modify. */ - - li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE - and t1, t1, t4 - or t1, t1, t3 - -#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 - or t1, t1, t0 -#endif - csrw mstatus, t1 // Update mstatus safely - - lw ra, 28*4(sp) // Recover return address - lw t0, 19*4(sp) // Recover t0 - lw t1, 18*4(sp) // Recover t1 - lw t2, 17*4(sp) // Recover t2 - lw s0, 12*4(sp) // Recover s0 - lw a0, 27*4(sp) // Recover a0 - lw a1, 26*4(sp) // Recover a1 - lw a2, 25*4(sp) // Recover a2 - lw a3, 24*4(sp) // Recover a3 - lw a4, 23*4(sp) // Recover a4 - lw a5, 22*4(sp) // Recover a5 - lw a6, 21*4(sp) // Recover a6 - lw a7, 20*4(sp) // Recover a7 - lw t3, 16*4(sp) // Recover t3 - lw t4, 15*4(sp) // Recover t4 - 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 - mret // 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)) - { */ - - la t0, _tx_thread_current_ptr // Pickup current thread pointer address - lw t1, 0(t0) // Pickup current thread pointer - - beqz t1, _tx_thread_idle_system_restore // If NULL, idle system 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 - - - la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address - lw t2, 0(t0) // Pickup thread execute pointer - - bne t1, t2, _tx_thread_preempt_restore // If higher-priority thread is ready, preempt - - -_tx_thread_no_preempt_restore: - /* Restore interrupted thread or ISR. */ - - /* Pickup the saved stack pointer. */ - /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ - - lw sp, 8(t1) // Switch back to thread's stack - - /* Recover floating point registers. */ -#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 - csrw fcsr, t0 // Restore fcsr -#endif - - /* Recover the saved context and return to the point of interrupt. */ - - /* Recover standard registers. */ - /* Restore registers, - Skip global pointer because that does not change */ - - lw t0, 30*4(sp) // Recover mepc - csrw mepc, t0 // Setup mepc - - /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. */ - - csrr t1, mstatus - li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode - li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE - and t1, t1, t4 - or t1, t1, t3 - -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t0, 0x2000 // Set FS bits for FP state - or t1, t1, t0 -#endif - csrw mstatus, t1 // Update mstatus safely - - lw ra, 28*4(sp) // Recover return address - lw t0, 19*4(sp) // Recover t0 - lw t1, 18*4(sp) // Recover t1 - lw t2, 17*4(sp) // Recover t2 - lw s0, 12*4(sp) // Recover s0 - lw a0, 27*4(sp) // Recover a0 - lw a1, 26*4(sp) // Recover a1 - lw a2, 25*4(sp) // Recover a2 - lw a3, 24*4(sp) // Recover a3 - lw a4, 23*4(sp) // Recover a4 - lw a5, 22*4(sp) // Recover a5 - lw a6, 21*4(sp) // Recover a6 - lw a7, 20*4(sp) // Recover a7 - lw t3, 16*4(sp) // Recover t3 - lw t4, 15*4(sp) // Recover t4 - 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 - mret // Return to point of interrupt - - /* } - else - { */ -_tx_thread_preempt_restore: - /* Instead of directly activating the thread again, ensure we save the - entire stack frame by saving the remaining registers. */ - - lw t0, 8(t1) // Pickup thread's stack pointer - ori t3, zero, 1 // Build interrupt stack type - sw t3, 0(t0) // Store stack type - - /* Store floating point preserved registers. */ -#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 -#endif - - /* Store standard preserved registers. */ - - sw x9, 11*4(t0) // Store s1 - sw x18, 10*4(t0) // Store s2 - sw x19, 9*4(t0) // Store s3 - sw x20, 8*4(t0) // Store s4 - sw x21, 7*4(t0) // Store s5 - sw x22, 6*4(t0) // Store s6 - sw x23, 5*4(t0) // Store s7 - sw x24, 4*4(t0) // Store s8 - sw x25, 3*4(t0) // Store s9 - sw x26, 2*4(t0) // Store s10 - sw x27, 1*4(t0) // Store s11 - // Note: s0 is already stored! - - /* Save the remaining time-slice and disable it. */ - /* if (_tx_timer_time_slice) - { */ - - la t0, _tx_timer_time_slice // Pickup time slice variable address - lw t2, 0(t0) // Pickup time slice - beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing - - /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice - _tx_timer_time_slice = 0; */ - - sw t2, 24(t1) // Save current time slice - sw x0, 0(t0) // Clear global time slice - - - /* } */ -_tx_thread_dont_save_ts: - /* Clear the current task pointer. */ - /* _tx_thread_current_ptr = TX_NULL; */ - - /* Return to the scheduler. */ - /* _tx_thread_schedule(); */ - - la t0, _tx_thread_current_ptr // Pickup current thread pointer address - sw x0, 0(t0) // Clear current thread pointer - - /* } */ - -_tx_thread_idle_system_restore: - /* Just return back to the scheduler! */ - j _tx_thread_schedule // Return to scheduler - -/* } */ diff --git a/ports/risc-v32/clang/src/tx_thread_context_save.S b/ports/risc-v32/clang/src/tx_thread_context_save.S deleted file mode 100644 index ffb302e3..00000000 --- a/ports/risc-v32/clang/src/tx_thread_context_save.S +++ /dev/null @@ -1,271 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - .section .text -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_thread_context_save RISC-V32/GNU */ -/* 6.4.x */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* 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 -_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) - sw ra, 28*4(sp) - */ - - sw t0, 19*4(sp) // Store t0 - sw t1, 18*4(sp) // Store t1 - - /* Check for a nested interrupt. */ - /* if (_tx_thread_system_state++) - { */ - - la t0, _tx_thread_system_state // Pickup addr of system state var - lw t1, 0(t0) // Pickup system state - addi t1, t1, 1 // Increment system state - sw t1, 0(t0) // Store system state - li t0, 1 - bgt t1, t0, _tx_thread_nested_save // If it's more than 1, nested interrupt - - /* First level interrupt, save the rest of the scratch registers and - check for a thread to preempt. */ - - sw t2, 17*4(sp) // Store t2 - sw s0, 12*4(sp) // Store s0 - sw a0, 27*4(sp) // Store a0 - sw a1, 26*4(sp) // Store a1 - sw a2, 25*4(sp) // Store a2 - sw a3, 24*4(sp) // Store a3 - sw a4, 23*4(sp) // Store a4 - sw a5, 22*4(sp) // Store a5 - sw a6, 21*4(sp) // Store a6 - sw a7, 20*4(sp) // Store a7 - sw t3, 16*4(sp) // Store t3 - sw t4, 15*4(sp) // Store t4 - sw t5, 14*4(sp) // Store t5 - sw t6, 13*4(sp) // Store t6 - - /* 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 - csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr -#endif - - csrr t0, mepc - sw t0, 30*4(sp) // Save it on the stack - - /* Save mstatus. */ - csrr t0, mstatus - sw t0, 29*4(sp) - - la t1, _tx_thread_current_ptr // Pickup address of current thread ptr - lw t2, 0(t1) // Pickup current thread pointer - beqz t2, _tx_thread_idle_system_save // If NULL, idle system was interrupted - - /* Save the current thread's stack pointer and switch to the system stack. */ - /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; - sp = _tx_thread_system_stack_ptr; */ - - sw sp, 8(t2) // Save stack pointer - la t0, _tx_thread_system_stack_ptr - lw sp, 0(t0) // Switch to system stack - - /* Call the ISR execution exit function if enabled. */ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_enter // Call the ISR execution enter function -#endif - - ret // Return to ISR - -_tx_thread_nested_save: - - /* Nested interrupt! Just save the scratch registers and return to the ISR. */ - - sw t2, 17*4(sp) // Store t2 - sw s0, 12*4(sp) // Store s0 - sw a0, 27*4(sp) // Store a0 - sw a1, 26*4(sp) // Store a1 - sw a2, 25*4(sp) // Store a2 - sw a3, 24*4(sp) // Store a3 - sw a4, 23*4(sp) // Store a4 - sw a5, 22*4(sp) // Store a5 - sw a6, 21*4(sp) // Store a6 - sw a7, 20*4(sp) // Store a7 - sw t3, 16*4(sp) // Store t3 - sw t4, 15*4(sp) // Store t4 - sw t5, 14*4(sp) // Store t5 - sw t6, 13*4(sp) // Store t6 - - /* 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 - csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr -#endif - - csrr t0, mepc - sw t0, 30*4(sp) // Save it on stack - - csrr t0, mstatus - sw t0, 29*4(sp) - - /* Call the ISR execution exit function if enabled. */ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_enter // Call the ISR execution enter function -#endif - - ret // Return to ISR - -_tx_thread_idle_system_save: - - -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - call _tx_execution_isr_enter // Call the ISR execution enter function -#endif - - /* Interrupt occurred in the scheduling loop. */ - - /* } -} */ -#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 - ret // Return to calling ISR diff --git a/ports/risc-v32/clang/src/tx_thread_schedule.S b/ports/risc-v32/clang/src/tx_thread_schedule.S deleted file mode 100644 index d5a54fa2..00000000 --- a/ports/risc-v32/clang/src/tx_thread_schedule.S +++ /dev/null @@ -1,318 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - - .section .text -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_thread_schedule RISC-V32/GNU */ -/* 6.4.x */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* 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 -_tx_thread_schedule: - - /* Enable interrupts. */ - - csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3) - - /* Wait for a thread to execute. */ - /* do - { */ -_tx_thread_schedule_loop: - - la t0, _tx_thread_execute_ptr // Pickup address of execute ptr - lw t1, 0(t0) // Pickup execute pointer - bnez t1, _tx_thread_ready_to_run // If non-NULL, a thread is ready to run - -#ifndef TX_NO_WFI - wfi // Wait for interrupt -#endif - j _tx_thread_schedule_loop // Check again - - /* } - while (_tx_thread_execute_ptr == TX_NULL); */ - -_tx_thread_ready_to_run: - - /* At this point, t1 contains the pointer to the thread to execute. - Lockout interrupts. */ - - csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) - - /* Check _tx_thread_execute_ptr again, in case an interrupt occurred - between the check and the disable. */ - - lw t1, 0(t0) // Pickup execute pointer - beqz t1, _tx_thread_schedule_loop // If NULL, go back to wait loop - - /* Yes! We have a thread to execute. */ - /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ - - la t0, _tx_thread_current_ptr // Pickup address of current thread - sw t1, 0(t0) // Setup current thread pointer - - /* Increment the run count for this thread. */ - /* _tx_thread_current_ptr -> tx_thread_run_count++; */ - - lw t2, 4(t1) // Pickup run count - addi t2, t2, 1 // Increment run count - sw t2, 4(t1) // Store run count - - /* Setup time-slice values. */ - /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ - - lw t2, 24(t1) // Pickup thread time-slice - la t3, _tx_timer_time_slice // Pickup address of time-slice - sw t2, 0(t3) // Setup time-slice - - /* Call the thread execution enter function if enabled. */ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - - call _tx_execution_thread_enter // Call the thread execution enter function -#endif - - /* Switch to the thread's stack. */ - /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ - - lw sp, 8(t1) // Switch to thread stack - - /* Determine the type of stack frame. */ - /* if (*sp) - { */ - - lw t0, 0(sp) // Pickup stack type - beqz t0, _tx_thread_solicited_return // If 0, solicited return - - /* Recover floating point registers. */ -#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 - 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 - - /* Recover standard registers. */ - - lw t0, 30*4(sp) // Recover mepc - 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) - li t1, 0x2000 // Set FS bits for FP state - or t0, t0, t1 -#endif - csrw mstatus, t0 // Set mstatus - - lw ra, 28*4(sp) // Recover return address - lw t0, 19*4(sp) // Recover t0 - lw t1, 18*4(sp) // Recover t1 - lw t2, 17*4(sp) // Recover t2 - lw s0, 12*4(sp) // Recover s0 - lw x9, 11*4(sp) // Recover s1 - lw a0, 27*4(sp) // Recover a0 - lw a1, 26*4(sp) // Recover a1 - lw a2, 25*4(sp) // Recover a2 - lw a3, 24*4(sp) // Recover a3 - lw a4, 23*4(sp) // Recover a4 - lw a5, 22*4(sp) // Recover a5 - lw a6, 21*4(sp) // Recover a6 - lw a7, 20*4(sp) // Recover a7 - lw t3, 16*4(sp) // Recover t3 - lw t4, 15*4(sp) // Recover t4 - lw t5, 14*4(sp) // Recover t5 - lw t6, 13*4(sp) // Recover t6 - lw x18, 10*4(sp) // Recover s2 - lw x19, 9*4(sp) // Recover s3 - lw x20, 8*4(sp) // Recover s4 - lw x21, 7*4(sp) // Recover s5 - lw x22, 6*4(sp) // Recover s6 - lw x23, 5*4(sp) // Recover s7 - lw x24, 4*4(sp) // Recover s8 - lw x25, 3*4(sp) // Recover s9 - 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 - mret // Return to thread - -_tx_thread_solicited_return: - - /* Recover floating point registers. */ -#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 - csrw fcsr, t0 // Restore fcsr -#endif - - /* Recover standard registers. */ - - lw t0, 14*4(sp) // Recover mstatus - csrw mstatus, t0 // Restore mstatus - - lw ra, 13*4(sp) // Recover return address - lw s0, 12*4(sp) // Recover s0 - lw s1, 11*4(sp) // Recover s1 - lw x18, 10*4(sp) // Recover s2 - lw x19, 9*4(sp) // Recover s3 - lw x20, 8*4(sp) // Recover s4 - lw x21, 7*4(sp) // Recover s5 - lw x22, 6*4(sp) // Recover s6 - lw x23, 5*4(sp) // Recover s7 - lw x24, 4*4(sp) // Recover s8 - lw x25, 3*4(sp) // Recover s9 - 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 - ret // Return to thread - -/* } */ diff --git a/ports/risc-v32/clang/src/tx_thread_stack_build.S b/ports/risc-v32/clang/src/tx_thread_stack_build.S deleted file mode 100644 index 2b8ebae1..00000000 --- a/ports/risc-v32/clang/src/tx_thread_stack_build.S +++ /dev/null @@ -1,221 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - - .section .text -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_thread_stack_build RISC-V32/GNU */ -/* 6.4.x */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* 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 -_tx_thread_stack_build: - - /* Build a fake interrupt frame. The form of the fake interrupt stack - on the RISC-V should look like the following after it is built: - Reg Index - Stack Top: 1 0 Interrupt stack frame type - x27 1 Initial s11 - x26 2 Initial s10 - x25 3 Initial s9 - x24 4 Initial s8 - x23 5 Initial s7 - x22 6 Initial s6 - x21 7 Initial s5 - x20 8 Initial s4 - x19 9 Initial s3 - x18 10 Initial s2 - x9 11 Initial s1 - x8 12 Initial s0 - x31 13 Initial t6 - x30 14 Initial t5 - x29 15 Initial t4 - x28 16 Initial t3 - x7 17 Initial t2 - x6 18 Initial t1 - x5 19 Initial t0 - x17 20 Initial a7 - x16 21 Initial a6 - x15 22 Initial a5 - x14 23 Initial a4 - x13 24 Initial a3 - x12 25 Initial a2 - x11 26 Initial a1 - x10 27 Initial a0 - x1 28 Initial ra - -- 29 reserved - 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 - - Stack Bottom: (higher memory address) */ - - lw t0, 16(a0) // Pickup end of stack area - li t1, ~15 // Build 16-byte alignment mask - and t0, t0, t1 // Make sure 16-byte alignment - - /* 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 - li t1, 1 // Build stack type - sw t1, 0*4(t0) // Place stack type on the top - sw zero, 1*4(t0) // Initial s11 - sw zero, 2*4(t0) // Initial s10 - sw zero, 3*4(t0) // Initial s9 - sw zero, 4*4(t0) // Initial s8 - sw zero, 5*4(t0) // Initial s7 - sw zero, 6*4(t0) // Initial s6 - sw zero, 7*4(t0) // Initial s5 - sw zero, 8*4(t0) // Initial s4 - sw zero, 9*4(t0) // Initial s3 - sw zero, 10*4(t0) // Initial s2 - sw zero, 11*4(t0) // Initial s1 - sw zero, 12*4(t0) // Initial s0 - sw zero, 13*4(t0) // Initial t6 - sw zero, 14*4(t0) // Initial t5 - sw zero, 15*4(t0) // Initial t4 - sw zero, 16*4(t0) // Initial t3 - sw zero, 17*4(t0) // Initial t2 - sw zero, 18*4(t0) // Initial t1 - sw zero, 19*4(t0) // Initial t0 - sw zero, 20*4(t0) // Initial a7 - sw zero, 21*4(t0) // Initial a6 - sw zero, 22*4(t0) // Initial a5 - sw zero, 23*4(t0) // Initial a4 - sw zero, 24*4(t0) // Initial a3 - sw zero, 25*4(t0) // Initial a2 - sw zero, 26*4(t0) // Initial a1 - 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) -#else - sw zero, 31*4(t0) // Reserved word (0) -#endif - - /* Setup stack pointer. */ - /* thread_ptr -> tx_thread_stack_ptr = t0; */ - - sw t0, 8(a0) // Save stack pointer in thread's - ret // control block and return -/* } */ diff --git a/ports/risc-v32/clang/src/tx_thread_system_return.S b/ports/risc-v32/clang/src/tx_thread_system_return.S deleted file mode 100644 index b54f54fa..00000000 --- a/ports/risc-v32/clang/src/tx_thread_system_return.S +++ /dev/null @@ -1,168 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - - .section .text -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_thread_system_return RISC-V32/GNU */ -/* 6.4.x */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function is target processor specific. It is used to transfer */ -/* control from a thread back to the 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 -_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 - - /* Store floating point preserved registers. */ -#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 - 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 zero, 0(sp) // Solicited stack type - sw ra, 13*4(sp) // Save return address - sw s0, 12*4(sp) // Save s0 - sw s1, 11*4(sp) // Save s1 - sw s2, 10*4(sp) // Save s2 - sw s3, 9*4(sp) // Save s3 - sw s4, 8*4(sp) // Save s4 - sw s5, 7*4(sp) // Save s5 - sw s6, 6*4(sp) // Save s6 - sw s7, 5*4(sp) // Save s7 - sw s8, 4*4(sp) // Save s8 - sw s9, 3*4(sp) // Save s9 - sw s10, 2*4(sp) // Save s10 - sw s11, 1*4(sp) // Save s11 - csrr t0, mstatus // Pickup mstatus - sw t0, 14*4(sp) // Save mstatus - - - /* Lockout interrupts. will be enabled in _tx_thread_schedule */ - - csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) - -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - - call _tx_execution_thread_exit // Call the thread execution exit function -#endif - - la t0, _tx_thread_current_ptr // Pickup address of pointer - lw t1, 0(t0) // Pickup current thread pointer - la t2, _tx_thread_system_stack_ptr // Pickup stack pointer address - - /* Save current stack and switch to system stack. */ - /* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP; - SP = _tx_thread_system_stack_ptr; */ - - sw sp, 8(t1) // Save stack pointer - lw sp, 0(t2) // Switch to system stack - - /* Determine if the time-slice is active. */ - /* if (_tx_timer_time_slice) - { */ - - la t4, _tx_timer_time_slice // Pickup time slice variable addr - lw t3, 0(t4) // Pickup time slice value - la t2, _tx_thread_schedule // Pickup address of scheduling loop - beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it - - /* 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; */ - - sw t3, 24(t1) // Save current time-slice for thread - sw zero, 0(t4) // Clear time-slice variable - - /* } */ -_tx_thread_dont_save_ts: - - /* Clear the current thread pointer. */ - /* _tx_thread_current_ptr = TX_NULL; */ - - sw x0, 0(t0) // Clear current thread pointer - jr t2 // Return to thread scheduler - -/* } */ diff --git a/ports/risc-v32/clang/src/tx_timer_interrupt.S b/ports/risc-v32/clang/src/tx_timer_interrupt.S deleted file mode 100644 index b64bf06b..00000000 --- a/ports/risc-v32/clang/src/tx_timer_interrupt.S +++ /dev/null @@ -1,204 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2026 Quintauris - * - * This 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 */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - .section .text - .align 4 -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_timer_interrupt RISC-V32/GNU */ -/* 6.2.1 */ -/* AUTHOR */ -/* */ -/* Francisco Merino, Quintauris */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function processes the hardware timer interrupt. This */ -/* processing includes incrementing the system clock and checking for */ -/* time slice and/or timer expiration. If either is found, the */ -/* interrupt context save/restore functions are called along with the */ -/* expiration functions. */ -/* */ -/* INPUT */ -/* */ -/* None */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _tx_timer_expiration_process Timer expiration processing */ -/* _tx_thread_time_slice Time slice interrupted thread */ -/* */ -/* CALLED BY */ -/* */ -/* interrupt vector */ -/* */ -/**************************************************************************/ -/* VOID _tx_timer_interrupt(VOID) -{ */ - .global _tx_timer_interrupt -_tx_timer_interrupt: - - /* Increment the system clock. */ - /* _tx_timer_system_clock++; */ - - la t0, _tx_timer_system_clock // Pickup address of system clock - lw t1, 0(t0) // Pickup system clock - la t2, _tx_timer_time_slice // Pickup address of time slice - lw t3, 0(t2) // Pickup time slice - addi t1, t1, 1 // Increment system clock - sw t1, 0(t0) // Store new system clock - li t6, 0 // Clear local expired flag - - /* Test for time-slice expiration. */ - /* if (_tx_timer_time_slice) - { */ - - beqz t3, _tx_timer_no_time_slice // If 0, skip time slice processing - addi t3, t3, -1 // Decrement the time slice - - /* Decrement the time_slice. */ - /* _tx_timer_time_slice--; */ - - sw t3, 0(t2) // Store new time slice - - /* Check for expiration. */ - /* if (_tx_timer_time_slice == 0) */ - - bgtz 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. */ - /* _tx_timer_expired_time_slice = TX_TRUE; */ - - la t4, _tx_timer_expired_time_slice // Get address of expired flag - sw t1, 0(t4) // Set expired flag (UINT) - ori t6, t6, 1 // Set local expired flag - - /* } */ - -_tx_timer_no_time_slice: - - /* Test for timer expiration. */ - /* if (*_tx_timer_current_ptr) - { */ - - la t0, _tx_timer_current_ptr // Pickup address of current ptr - lw t1, 0(t0) // Pickup current pointer (word) - lw t3, 0(t1) // Pickup the current timer entry (word) - la t2, _tx_timer_expired // Pickup address of timer expired flag - li t4, 1 // Build TX_TRUE flag - beqz t3, _tx_timer_no_timer // If NULL, no timer has expired - - /* Set expiration flag. */ - /* _tx_timer_expired = TX_TRUE; */ - - ori t6, t6, 2 // Set local expired flag - sw t4, 0(t2) // Set expired flag in memory (UINT) - j _tx_timer_done // Finished timer processing - - - /* } - else - { */ -_tx_timer_no_timer: - - /* No timer expired, increment the timer pointer. */ - /* _tx_timer_current_ptr++; */ - - /* Check for wrap-around. */ - /* if (_tx_timer_current_ptr == _tx_timer_list_end) */ - - la t2, _tx_timer_list_end // Pickup address of list end pointer - lw t3, 0(t2) // Pickup actual list end - addi t1, t1, 4 // Point to next timer entry - sw t1, 0(t0) // Store new timer pointer - bne t1, t3, _tx_timer_skip_wrap // If not same, good pointer - - /* Wrap to beginning of list. */ - /* _tx_timer_current_ptr = _tx_timer_list_start; */ - - la t2, _tx_timer_list_start // Pickup address of list start pointer - lw t4, 0(t2) // Pickup start of the list - sw t4, 0(t0) // Store new timer pointer - - -_tx_timer_skip_wrap: - /* } */ - -_tx_timer_done: - - - /* See if anything has expired. */ - /* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) - { */ - - beqz t6, _tx_timer_nothing_expired // If nothing expired skip the rest - addi sp, sp, -16 // Allocate some storage on the stack - sw t6, 0(sp) // Save local expired flag - sw ra, 4(sp) // Save ra - - /* Did a timer expire? */ - /* if (_tx_timer_expired) - { */ - - andi t2, t6, 2 // Isolate the timer expired bit - beqz t2, _tx_timer_dont_activate // No, timer not expired - - /* Call the timer expiration processing. */ - /* _tx_timer_expiration_process(void); */ - - call _tx_timer_expiration_process // Call _tx_timer_expiration_process - lw t6, 0(sp) // Recover local expired flag - - /* } */ -_tx_timer_dont_activate: - - /* Did time slice expire? */ - /* if (_tx_timer_expired_time_slice) - { */ - - andi t2, t6, 1 // Is the timer expired bit set? - beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing - - /* Time slice interrupted thread. */ - /* _tx_thread_time_slice(); */ - - call _tx_thread_time_slice // Call time slice - - /* } */ - -_tx_timer_not_ts_expiration: - - lw ra, 4(sp) // Recover ra - addi sp, sp, 16 // Recover stack space - /* } */ - -_tx_timer_nothing_expired: - - ret - -/* } */
\ No newline at end of file diff --git a/ports/risc-v32/common/tx_port_riscv32_common.h b/ports/risc-v32/common/tx_port_riscv32_common.h new file mode 100644 index 00000000..886565a8 --- /dev/null +++ b/ports/risc-v32/common/tx_port_riscv32_common.h @@ -0,0 +1,268 @@ +/*************************************************************************** + * 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 */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_riscv32_common.h RISC-V32 */ +/* 6.4.x */ +/* */ +/* DESCRIPTION */ +/* */ +/* Shared port definitions for all RISC-V32 toolchain ports (GNU, */ +/* Clang, etc.). Each toolchain's tx_port.h includes this file and */ +/* may add toolchain-specific definitions afterwards. */ +/* */ +/**************************************************************************/ + +/* This file is included from a toolchain-specific tx_port.h; do not */ +/* include it directly. */ + +#ifndef TX_PORT_H +#error "Include tx_port.h, not tx_port_riscv32_common.h directly." +#endif + + +#ifndef __ASSEMBLER__ + +/* Include for memset. */ +#include <string.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 */ + +#endif /* __ASSEMBLER__ */ + + +/* Define ThreadX basic types for this port. */ + +#define VOID void + +#ifndef __ASSEMBLER__ +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 +#endif /* __ASSEMBLER__ */ + + + + +/* 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 1024 /* 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 RISC-V port. */ + +#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ +#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */ + + +/* 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. */ + +#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. */ + +#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. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 +#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 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 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. */ + +/* Expose helper used to perform an atomic read/modify/write of mstatus. + The helper composes and returns the posture per ThreadX contract. */ +#ifndef __ASSEMBLER__ +UINT _tx_thread_interrupt_control(UINT new_posture); +#endif + +#ifdef TX_DISABLE_INLINE + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory"); +#define TX_RESTORE { \ + unsigned long _temp_mstatus; \ + __asm__ volatile( \ + "csrc mstatus, 8\n" \ + "andi %0, %1, 8\n" \ + "csrs mstatus, %0" \ + : "=&r" (_temp_mstatus) \ + : "r" (interrupt_save) \ + : "memory"); \ + } + +#else + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); +#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); + +#endif /* TX_DISABLE_INLINE */ + + +/* 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 diff --git a/ports/risc-v32/gnu/CMakeLists.txt b/ports/risc-v32/gnu/CMakeLists.txt index 9357c697..05000757 100644 --- a/ports/risc-v32/gnu/CMakeLists.txt +++ b/ports/risc-v32/gnu/CMakeLists.txt @@ -1,19 +1,7 @@ +include(${CMAKE_CURRENT_LIST_DIR}/../../../cmake/threadx_riscv_port.cmake) -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_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 +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-v32/gnu/example_build/core_v_mcu/CMakeLists.txt b/ports/risc-v32/gnu/example_build/core_v_mcu/CMakeLists.txt new file mode 100644 index 00000000..662914d1 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +project(demo_threadx_core_v_mcu LANGUAGES C ASM) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(CORE_V_MCU_DIR ${CMAKE_CURRENT_LIST_DIR}) +set(THREADX_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../..) +set(TX_USER_FILE ${CORE_V_MCU_DIR}/include/tx_user.h) + +set(THREADX_ARCH "risc-v32") +set(THREADX_TOOLCHAIN "gnu") + +message(STATUS "Toolchain file: ${CMAKE_TOOLCHAIN_FILE}") +message(STATUS "C compiler: ${CMAKE_C_COMPILER}") + +add_subdirectory(${THREADX_ROOT} threadx) +target_include_directories(threadx PRIVATE ${CORE_V_MCU_DIR}/include) + +set(SRCS + ${CORE_V_MCU_DIR}/crt0.S + ${CORE_V_MCU_DIR}/vectors.S + ${CORE_V_MCU_DIR}/tx_initialize_low_level.S + ${CORE_V_MCU_DIR}/bsp/irq.c + ${CORE_V_MCU_DIR}/bsp/timer_irq.c + ${CORE_V_MCU_DIR}/bsp/fll.c + ${CORE_V_MCU_DIR}/bsp/gpio.c + ${CORE_V_MCU_DIR}/bsp/uart_driver.c + ${CORE_V_MCU_DIR}/bsp/i2c_master.c + ${CORE_V_MCU_DIR}/bsp/temp_sensor.c + ${CORE_V_MCU_DIR}/bsp/system_core_v_mcu.c + ${CORE_V_MCU_DIR}/bsp/string.c + ${CORE_V_MCU_DIR}/demo_threadx.c +) + +add_executable(demo_threadx ${SRCS}) +set_target_properties(demo_threadx PROPERTIES OUTPUT_NAME "demo_threadx.elf") + +target_include_directories(demo_threadx PRIVATE + ${CORE_V_MCU_DIR}/include + ${THREADX_ROOT}/common/inc + ${THREADX_ROOT}/ports/risc-v32/gnu/inc +) + +target_link_libraries(demo_threadx PRIVATE threadx gcc) + +target_link_options(demo_threadx PRIVATE + -T${CORE_V_MCU_DIR}/link.ld + -nostartfiles + -nodefaultlibs + -Wl,--gc-sections + -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.map +) + +target_compile_options(demo_threadx PRIVATE + -Os + -g + -Wall + -Wextra + -ffreestanding + -ffunction-sections + -fdata-sections + -DTX_INCLUDE_USER_DEFINE_FILE +) + +add_custom_command(TARGET demo_threadx POST_BUILD + COMMAND ${OBJCOPY} -O binary $<TARGET_FILE:demo_threadx> ${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.bin + COMMENT "Generating demo_threadx.bin" +) diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/README.md b/ports/risc-v32/gnu/example_build/core_v_mcu/README.md new file mode 100644 index 00000000..41f45dab --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/README.md @@ -0,0 +1,504 @@ +# ThreadX Port for CORE-V MCU + +This directory contains the Board Support Package (BSP) and demo application for +running Eclipse ThreadX on the +[CORE-V MCU](https://github.com/openhwgroup/core-v-mcu) — an open-source 32-bit +RISC-V SoC based on the CV32E40P core (RV32IMC). The reference hardware is a +[Digilent Nexys A7](https://digilent.com/reference/programmable-logic/nexys-a7/start) +FPGA board running the synthesised CORE-V MCU bitstream. + +--- + +## Table of Contents + +1. [Hardware overview](#1-hardware-overview) +2. [Software prerequisites](#2-software-prerequisites) +3. [Directory structure](#3-directory-structure) +4. [Architecture notes](#4-architecture-notes) +5. [Memory map](#5-memory-map) +6. [Building](#6-building) +7. [Flashing and debugging](#7-flashing-and-debugging) +8. [BSP API reference](#8-bsp-api-reference) +9. [Unit tests](#9-unit-tests) +10. [Adapting to a different board](#10-adapting-to-a-different-board) +11. [Setup and deployment scripts](#11-setup-and-deployment-scripts) + +--- + +## 1. Hardware overview + +| Item | Detail | +|------|--------| +| CPU | CV32E40P — RV32IMC, in-order, 4-stage pipeline | +| ISA | `rv32imc_zicsr` (integer, compressed, multiply/divide, CSR instructions) | +| L2 SRAM | 512 KB at `0x1c000000` (code + data + stack) | +| Interrupt controller | PULP APB interrupt controller (32 lines, **not** a standard CLINT) | +| Timer | PULP FC Timer at `0x1A10B000`, 32 kHz reference clock | +| UART | UDMA UART channel 0 at `0x1A102080` | +| GPIO | PULP GPIO controller at `0x1A101000` | +| FLL | Frequency Locked Loop — 5 MHz input (FPGA), 50 MHz output | +| Debug probe | [Ashling Opella LD](https://www.ashling.com/ashling-opella-ld/) via JTAG | + +The CV32E40P does **not** implement the standard RISC-V CLINT (`mip`/`mie` per-source +masking). Individual interrupt lines are enabled and cleared through PULP APB +registers, and `mstatus.MIE` (bit 3) acts as the single global enable. + +--- + +## 2. Software prerequisites + +Run `install_deps.sh` to install all dependencies in one step: + +```bash +bash install_deps.sh +``` + +Or install individually: + +| Tool | Minimum version | Notes | +|------|----------------|-------| +| `riscv-none-elf-gcc` | 15.x | xPack riscv-none-elf-gcc — run `bash install_deps.sh` | +| CMake | 3.15 | `apt install cmake` | +| Ninja | 1.10 | `apt install ninja-build` | +| OpenOCD | 0.12 | `apt install openocd` | +| GDB | any multiarch | `apt install gdb-multiarch` | + +> **Note:** Use the [xPack riscv-none-elf-gcc](https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack) +> toolchain — a cross-platform (Linux/macOS/Windows) multilib bare-metal +> toolchain analogous to `arm-none-eabi-gcc`. Its multilib includes +> rv32imc/ilp32 (soft-float) libgcc required for the CV32E40P. Do **not** +> use `riscv32-unknown-elf-gcc` (riscv-collab) — that release is built +> `--disable-multilib --with-abi=ilp32d` and cannot link soft-float objects. + +--- + +## 3. Directory structure + +``` +core_v_mcu/ +├── bsp/ Board Support Package +│ ├── fll.c Frequency Locked Loop driver +│ ├── gpio.c GPIO driver +│ ├── irq.c PULP APB interrupt controller driver +│ ├── string.c Freestanding memset/memcpy shim +│ ├── system_core_v_mcu.c Top-level BSP init and ISR dispatcher +│ ├── timer_irq.c PULP FC Timer driver +│ └── uart_driver.c UDMA UART driver +├── include/ BSP headers +│ ├── bits.h Bit-manipulation macros +│ ├── csr.h CSR access macros +│ ├── fll.h +│ ├── gpio.h +│ ├── io.h MMIO read/write inlines +│ ├── irq.h +│ ├── memory_map.h Peripheral base addresses +│ ├── properties.h Clock/frequency constants +│ ├── pulp_mem_map.h PULP peripheral register offsets +│ ├── string.h Freestanding string shim header +│ ├── system_core_v_mcu.h +│ ├── timer.h +│ ├── timer_irq.h +│ ├── tx_user.h ThreadX compile-time configuration +│ └── uart_driver.h +├── tests/ Host-compiled unit tests (no cross-compiler needed) +│ ├── mock/ +│ │ ├── mmio_mock.c Replaces io.h MMIO inlines with a software map +│ │ └── mmio_mock.h +│ ├── test_irq.c Tests for irq.c +│ ├── test_timer.c Tests for timer_irq.c +│ └── CMakeLists.txt +├── crt0.S C runtime startup (clear BSS, call main) +├── vectors.S 32-entry vectored interrupt table +├── tx_initialize_low_level.S ThreadX platform init (mtvec, stack pointer) +├── link.ld Linker script +├── demo_threadx.c Demo application (blinky + UART heartbeat) +├── CMakeLists.txt Build definition +├── build.sh One-shot build script +├── gdb_init GDB startup script +└── openocd-nexys-Ashling-Opella-LD.cfg OpenOCD configuration +``` + +The ThreadX kernel sources are **not** duplicated here; they are referenced from the +repository root via `THREADX_ROOT`. + +--- + +## 4. Architecture notes + +### 4.1 Interrupt model + +The CV32E40P uses a PULP/PULPissimo-style interrupt controller rather than the +standard RISC-V CLINT. Key differences: + +- **32 direct interrupt lines** connect to the core. `mcause` for an external + interrupt is `0x80000000 | N`, where `N` (bits 4–0) is the line number. +- **Per-line masking** is done through APB registers in the PULP IRQ controller + (`IRQ_REG_MASK_SET_OFFSET` / `IRQ_REG_MASK_CLEAR_OFFSET`) — not through the `mie` + CSR. +- **Global enable** is `mstatus.MIE` (bit 3). ThreadX manages this itself: the + scheduler sets MIE just before entering the WFI idle loop in + `_tx_thread_schedule`. + +ISR dispatch flow: + +``` +CPU takes interrupt + → PC jumps to mtvec base (vectored mode, bit 0 = 1) + → vectors.S entry for line N → tx_trap_entry + → tx_trap_entry saves registers, calls _tx_thread_context_save + → tx_trap_handler(mcause, mepc, mtval) dispatches via isr_table[mcause & 0x1f] + → ThreadX timer ISR (line 10) calls _tx_timer_interrupt + → _tx_thread_context_restore (never returns to tx_trap_entry) +``` + +### 4.2 `mtvec` alignment + +The CV32E40P requires the vector table base to be **256-byte aligned**. The linker +script places `.vectors` at `0x1c000800`, which satisfies this. `mtvec` is written +as `0x1c000801` (base + vectored-mode bit). + +### 4.3 ThreadX timer tick + +- Reference clock: 32 768 Hz (ARCHI_REF_CLOCK) +- Tick rate: 100 Hz → compare value 327 (~0.1 % drift) +- The timer auto-reloads on compare match (cycle mode) +- `_tx_timer_interrupt` is registered in `isr_table[10]` during `system_init()` + +### 4.4 FLL and clock + +On the Nexys A7 FPGA, the FLL input is 5 MHz (`ARCHI_FPGA_FREQUENCY`). After +`pi_fll_init()` the system clock is 50 MHz (`DEFAULT_SYSTEM_CLOCK`). The UART baud +rate divisor is computed from this 50 MHz clock. + +### 4.5 Freestanding build + +The port builds with `-ffreestanding -nodefaultlibs` — no newlib or libc. +`bsp/string.c` provides minimal `memset` and `memcpy` for ThreadX internal use. + +--- + +## 5. Memory map + +| Region | Start | Size | Contents | +|--------|-------|------|----------| +| Vector table | `0x1c000800` | 128 B | 32 × 4-byte jump instructions to `tx_trap_entry` | +| `.text` (boot address) | `0x1c000880` | — | Code + read-only data | +| `.data` | after `.text` | — | Initialised data | +| `.bss` | after `.data` | — | Zero-initialised data | +| ThreadX free memory | after `.bss` | — | Heap pools, thread stacks | +| Stack | top of L2 | 8 KB | Initial/idle stack grows downward from `0x1c080000` | + +L2 total: 512 KB (`0x1c000000`–`0x1c07ffff`). + +Peripheral base addresses (see `include/memory_map.h`): + +| Peripheral | Address | +|------------|---------| +| PULP IRQ controller | `0x1A109800` | +| PULP FC Timer | `0x1A10B000` | +| PULP GPIO | `0x1A101000` | +| UDMA UART ch0 | `0x1A102080` | +| FLL | `0x1A100000` | + +--- + +## 6. Building + +### Quick start + +```bash +cd ports/risc-v32/gnu/example_build/core_v_mcu +bash build.sh +``` + +The script configures and builds with Ninja. The output is: + +``` +build/demo_threadx.elf — ELF with debug symbols +build/demo_threadx.bin — raw binary for flashing +build/demo_threadx.map — linker map +``` + +### Manual CMake invocation + +```bash +THREADX_ROOT=$(realpath ../../../../..) +cmake -B build -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake" \ + . +cmake --build build +``` + +### Toolchain file + +`${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake` sets: + +``` +CMAKE_C_COMPILER riscv-none-elf-gcc +CMAKE_ASM_COMPILER riscv-none-elf-gcc +CMAKE_OBJCOPY riscv-none-elf-objcopy +CMAKE_C_FLAGS -march=rv32imc_zicsr -mabi=ilp32 -mcmodel=medlow +``` + +--- + +## 7. Flashing and debugging + +### 7.1 Quick deploy (recommended) + +Use `deploy.sh` to automate the entire OpenOCD + GDB workflow in one command: + +```bash +# Flash and run (leave target running after GDB exits): +bash deploy.sh + +# Build first, then flash and run: +bash deploy.sh --build + +# Flash and stop at main for interactive debugging: +bash deploy.sh --debug + +# Override the ELF or the OpenOCD config: +bash deploy.sh --elf path/to/my.elf --openocd-cfg path/to/other.cfg +``` + +> **First time only:** run `bash ../../../../../samplex-fd/OpenHW/scripts/setup_opella.sh` +> (or the equivalent path) once to install the udev rule for the Opella LD. +> See [Section 11](#11-setup-and-deployment-scripts) for details. + +### 7.2 Manual procedure + +#### Connect hardware + +1. Connect the Ashling Opella LD to the Nexys A7 JTAG header. +2. Connect the USB-UART cable (CORE-V MCU UART0 mapped to USB micro-B on Nexys A7). +3. Power on the board. + +#### Start OpenOCD + +```bash +openocd -f openocd-nexys-Ashling-Opella-LD.cfg +``` + +Expected output ends with `Ready for Remote Connections`. OpenOCD listens on +port 3333 (GDB) and 4444 (telnet). + +#### Flash and run with GDB + +In a second terminal: + +```bash +riscv-none-elf-gdb --command=gdb_init +``` + +`gdb_init` connects to OpenOCD, loads the ELF, sets a breakpoint at `main`, and +continues. You should see the LED on pin 5 blinking at 1 Hz and the UART printing +`ThreadX on CORE-V MCU` followed by periodic `.` heartbeats at 115 200 baud. + +#### UART monitor + +```bash +minicom -b 115200 -D /dev/ttyUSBx # adjust device as needed +``` + +#### Useful GDB commands + +``` +(gdb) info threads — list ThreadX threads +(gdb) thread 2 — switch to a thread +(gdb) bt — backtrace +(gdb) monitor halt — halt via OpenOCD +(gdb) monitor resume — resume via OpenOCD +``` + +--- + +## 8. BSP API reference + +### `system_core_v_mcu.h` + +```c +void system_init(void); +``` +Initialises FLL, UART, IRQ controller, and FC Timer. Must be called once from +`main()` before `tx_kernel_enter()`. + +### `uart_driver.h` + +```c +int uart_init(uint8_t uart_id, uint32_t baudrate, uint32_t periph_freq); +void uart_write_byte(uint8_t uart_id, uint8_t c); +int uart_read_byte(uint8_t uart_id); /* returns -1 if no data */ +void uart_write_str(uint8_t uart_id, const char *str); +void uart_write_buf(uint8_t uart_id, const uint8_t *buf, uint32_t len); +``` + +`uart_id` 0 is the console UART. `uart_read_byte` is non-blocking. + +### `gpio.h` + +```c +void gpio_init(void); +void gpio_set_output(uint32_t pin_mask); /* configure pins as outputs */ +void gpio_set(uint32_t pin_mask); /* drive high */ +void gpio_clear(uint32_t pin_mask); /* drive low */ +void gpio_toggle(uint32_t pin_mask); +``` + +`pin_mask` is a bitmask where bit N corresponds to GPIO pin N. + +### `irq.h` + +```c +void pulp_irq_init(void); +void irq_enable(uint32_t irq_id); +void irq_disable(uint32_t irq_id); +void irq_clint_enable(void); /* set mstatus.MIE */ +void irq_clint_disable(void); /* clear mstatus.MIE */ +``` + +`irq_id` values are defined as `IRQ_FC_EVT_*` in `irq.h`. The timer uses +`IRQ_FC_EVT_TIMER0_LO` (= 10). + +### `timer_irq.h` + +```c +void timer_irq_init(uint32_t ticks); +void timer_irq_set_timeout(uint32_t ticks, bool enable); +uint32_t timer_irq_cycle_get_32(void); +``` + +### Registering a custom ISR + +Add a function pointer to `isr_table` before calling `tx_kernel_enter()`: + +```c +extern void (*isr_table[32])(void); + +static void my_irq_handler(void) { /* ... */ } + +/* In main() or tx_application_define(), before enabling the line: */ +isr_table[MY_IRQ_LINE] = my_irq_handler; +irq_enable(MY_IRQ_LINE); +``` + +--- + +## 9. Unit tests + +The tests compile for the **host** (no cross-compiler required) using a software +MMIO mock that backs the peripheral register space with a `uint32_t` array. + +```bash +cd tests +cmake -B build -G Ninja +cmake --build build +./build/tx_core_v_mcu_tests +``` + +Expected output: + +``` +irq_tests: PASS +timer_tests: PASS +``` + +The mock is enabled by defining `CORE_V_MCU_MMIO_MOCK` before including `io.h`. +`mmio_mock.c` provides `mock_reg_read` / `mock_reg_write` helpers for assertions. + +--- + +## 10. Adapting to a different board + +To port to a different CORE-V MCU carrier board: + +1. **Clock frequencies** — update `ARCHI_REF_CLOCK`, `ARCHI_FPGA_FREQUENCY`, and + `DEFAULT_SYSTEM_CLOCK` in `include/properties.h`. + +2. **Memory layout** — adjust `ORIGIN` and `LENGTH` for `L2` in `link.ld` and + update `__boot_address` if the boot ROM routes differently. + +3. **mtvec base** — if `.vectors` moves, update the address in `link.ld`. The + 256-byte alignment requirement is a hard CV32E40P constraint. + +4. **Debug probe** — replace `openocd-nexys-Ashling-Opella-LD.cfg` with a config + matching your probe (e.g., `interface jlink` for a J-Link). + +5. **GPIO pin** — `DEMO_LED_PIN` in `demo_threadx.c` selects the LED. Change to + match your board's LED assignment. + +--- + +## 11. Setup and deployment scripts + +### 11.1 `setup_opella.sh` — one-time host setup + +Located in `samplex-fd/OpenHW/scripts/setup_opella.sh`. Run **once per machine** +to grant user-space access to the Ashling Opella LD USB device. + +```bash +# Native Linux: +sudo bash samplex-fd/OpenHW/scripts/setup_opella.sh + +# WSL (also attempts usbipd-win USB forwarding): +bash samplex-fd/OpenHW/scripts/setup_opella.sh +``` + +What it does: + +| Step | Native Linux | WSL | +|------|-------------|-----| +| Write `/etc/udev/rules.d/99-ashling-opella.rules` | ✓ | ✓ | +| Add user to `plugdev` group | ✓ | ✓ | +| Reload udev | ✓ | ✓ | +| `usbipd.exe attach --wsl` (v3: `wsl attach`) | — | automatic | + +> **WSL — one-time bind (Windows admin required):** +> Before the first attach, run this once in an **elevated (Run as Administrator) PowerShell** on the Windows host: +> ```powershell +> usbipd bind --hardware-id 0b6b:0040 +> ``` +> After binding, `setup_opella.sh` handles subsequent attaches automatically. + +> **WSL — if attach fails with "not USBIP capable" (usbipd-win v3 + Ubuntu 22.04+):** +> Ubuntu 22.04 and 24.04 enable systemd by default. usbipd-win **v3** has a +> known bug where it incorrectly reports the kernel as not USBIP capable when +> systemd is running. **Upgrade usbipd-win to v4 or later:** +> <https://github.com/dorssel/usbipd-win/releases> +> +> If you are on an older WSL2 kernel without USBIP support, first run: +> ```powershell +> wsl --update +> wsl --shutdown +> ``` + +After running, **re-plug the probe**. On WSL, re-run the script after each WSL restart. + +### 11.2 `deploy.sh` — flash and run + +```bash +# Flash and run (leave target running): +bash deploy.sh + +# Build first, then flash: +bash deploy.sh --build + +# Flash and stop at main for interactive debug session: +bash deploy.sh --debug +``` + +The script starts OpenOCD in the background, waits for it to become ready, +then drives `riscv-none-elf-gdb` to load the ELF. OpenOCD is always +stopped on exit (including Ctrl-C). + +--- + +## Licence + +New files in this directory are © 2026 Eclipse ThreadX contributors, MIT. + +Files derived from +[core-v-freertos](https://github.com/openhwgroup/core-v-freertos) retain their +original Apache-2.0 copyright notices (ETH Zurich, GreenWaves Technologies, Wind +River Systems, SiFive Inc.) and are dual-licensed `Apache-2.0 AND MIT` (or +`(Apache-2.0 OR BSD-2-Clause) AND MIT` for `crt0.S`). See individual file headers. diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/fll.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/fll.c new file mode 100644 index 00000000..46dce857 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/fll.c @@ -0,0 +1,209 @@ +/***************************************************************************/ +/* Copyright 2020 GreenWaves Technologies + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#include <stddef.h> +#include <stdint.h> + +#include "bits.h" +#include "csr.h" +#include "fll.h" +#include "irq.h" +#include "properties.h" +#include "system_core_v_mcu.h" + +#define FLL_LOG2_MAXDCO 29U +#define FLL_LOG2_REFCLK ARCHI_REF_CLOCK_LOG2 +#define FLL_LOG2_MAXM (FLL_LOG2_MAXDCO - FLL_LOG2_REFCLK) + +static volatile uint32_t flls_frequency[FLL_NUM]; + +static uint32_t fll_max_u32(uint32_t a, uint32_t b) +{ + return (a > b) ? a : b; +} + +static uint32_t fll_fl1(uint32_t value) +{ + return (uint32_t)(31U - (uint32_t)__builtin_clz(value)); +} + +static uint32_t fll_get_mult_div_from_frequency(uint32_t freq, uint32_t *mult, + uint32_t *div) +{ + uint32_t fref = FLL_REF_CLK; + uint32_t log2_m; + uint32_t d; + uint32_t m; + uint32_t fres; + + if ((freq == 0U) || (mult == NULL) || (div == NULL)) + { + if (mult != NULL) + { + *mult = 0U; + } + if (div != NULL) + { + *div = 0U; + } + return 0U; + } + + if (freq > fref) + { + log2_m = fll_fl1(freq) - fll_fl1(fref); + } + else + { + log2_m = 0U; + } + + if (FLL_LOG2_MAXM > log2_m) + { + d = fll_max_u32(1U, (FLL_LOG2_MAXM - log2_m) >> 1U); + } + else + { + d = 1U; + } + + m = (freq << d) / fref; + fres = (fref * m + (1UL << (d - 1U))) >> d; + + *mult = m; + *div = d + 1U; + return fres; +} + +static uint32_t fll_get_frequency_from_mult_div(uint32_t mult, uint32_t div) +{ + uint32_t fref = FLL_REF_CLK; + + if (div == 0U) + { + return fref * mult; + } + + return (fref * mult) >> (div - 1U); +} + +int pi_fll_set_frequency(fll_type_t which_fll, uint32_t frequency, int check) +{ + uint32_t mult; + uint32_t div; + uint32_t reg1; + uint32_t saved_irq; + + (void)check; + + if ((uint32_t)which_fll >= FLL_NUM) + { + return -1; + } + + if (frequency == 0U) + { + return -1; + } + + saved_irq = irq_clint_disable(); + (void)fll_get_mult_div_from_frequency(frequency, &mult, &div); + + reg1 = FLL_CTRL[which_fll].FLL_CONF1; + reg1 &= ~FLL_CTRL_CONF1_MULTI_FACTOR_MASK; + reg1 |= REG_SET(FLL_CTRL_CONF1_MULTI_FACTOR, mult); + reg1 &= ~FLL_CTRL_CONF1_CLK_OUT_DIV_MASK; + reg1 |= REG_SET(FLL_CTRL_CONF1_CLK_OUT_DIV, div); + FLL_CTRL[which_fll].FLL_CONF1 = reg1; + + flls_frequency[which_fll] = frequency; + if (which_fll == FLL_SOC) + { + system_core_clock = frequency; + } + + if ((saved_irq & MSTATUS_IE) != 0U) + { + (void)irq_clint_enable(); + } + + return (int)frequency; +} + +void pi_fll_init(fll_type_t which_fll, uint32_t ret_state) +{ + uint32_t reg1; + + if ((uint32_t)which_fll >= FLL_NUM) + { + return; + } + + if (ret_state != 0U) + { + (void)pi_fll_get_frequency(which_fll, 1U); + return; + } + + reg1 = FLL_CTRL[which_fll].FLL_CONF1; + if (REG_GET(FLL_CTRL_CONF1_MODE, reg1) == 0U) + { + uint32_t reg2 = FLL_CTRL[which_fll].FLL_CONF2; + uint32_t regint = FLL_CTRL[which_fll].FLL_INTEGRATOR; + + reg2 &= ~FLL_CTRL_CONF2_ASSERT_CYCLES_MASK; + reg2 |= REG_SET(FLL_CTRL_CONF2_ASSERT_CYCLES, 0x6U); + reg2 &= ~FLL_CTRL_CONF2_LOCK_TOLERANCE_MASK; + reg2 |= REG_SET(FLL_CTRL_CONF2_LOCK_TOLERANCE, 0x50U); + FLL_CTRL[which_fll].FLL_CONF2 = reg2; + + regint &= ~FLL_CTRL_INTEGRATOR_INT_PART_MASK; + regint |= REG_SET(FLL_CTRL_INTEGRATOR_INT_PART, 332U); + FLL_CTRL[which_fll].FLL_INTEGRATOR = regint; + + reg1 &= ~FLL_CTRL_CONF1_OUTPUT_LOCK_EN_MASK; + reg1 |= REG_SET(FLL_CTRL_CONF1_OUTPUT_LOCK_EN, 1U); + reg1 &= ~FLL_CTRL_CONF1_MODE_MASK; + reg1 |= REG_SET(FLL_CTRL_CONF1_MODE, 1U); + FLL_CTRL[which_fll].FLL_CONF1 = reg1; + } + + if (flls_frequency[which_fll] != 0U) + { + (void)pi_fll_set_frequency(which_fll, flls_frequency[which_fll], 0); + } + else + { + flls_frequency[which_fll] = fll_get_frequency_from_mult_div( + REG_GET(FLL_CTRL_CONF1_MULTI_FACTOR, reg1), + REG_GET(FLL_CTRL_CONF1_CLK_OUT_DIV, reg1)); + } +} + +int pi_fll_get_frequency(fll_type_t which_fll, uint8_t real) +{ + if ((uint32_t)which_fll >= FLL_NUM) + { + return -1; + } + + if (real != 0U) + { + flls_frequency[which_fll] = fll_get_frequency_from_mult_div( + FLL_CTRL[which_fll].FLL_STATUS, + REG_GET(FLL_CTRL_CONF1_CLK_OUT_DIV, FLL_CTRL[which_fll].FLL_CONF1)); + } + + return (int)flls_frequency[which_fll]; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/gpio.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/gpio.c new file mode 100644 index 00000000..ddeba5b5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/gpio.c @@ -0,0 +1,128 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <stdint.h> + +#include "pulp_mem_map.h" +#include "io.h" +#include "gpio.h" + +/* APB SOC CTRL pad-mux interface (apb_soc_ctrl v1.0.0): + * Each IO pad has a dedicated 32-bit register at base + 0x400 + pad_index*4. + * PWDATA[1:0] = mux function (0=sys, 1=perio, 2=apbio/GPIO, 3=fpgaio) + * PWDATA[13:8] = pad config (drive/pull, optional) + * + * FUNC_C (2) routes the pad to the GPIO (apbio) controller. + * For the standard GPIO pins: io_pad = gpio_pin + GPIO_IO_PAD_OFFSET (=7). + * Verified in pad_control.sv: apbio[N] ↔ io_pad[N+7] when pad_mux[N+7]==2. */ +#define APB_SOC_PADMUX_BASE 0x400U +#define PINMUX_FUNC_C 2U +#define GPIO_IO_PAD_OFFSET 7U + +static void gpio_pinmux_set_func_c(uint32_t pin_mask) +{ + for (uint32_t gpio_pin = 0U; gpio_pin < 32U; gpio_pin++) + { + if ((pin_mask & (1UL << gpio_pin)) == 0U) + { + continue; + } + uint32_t io_pad = gpio_pin + GPIO_IO_PAD_OFFSET; + uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE + + io_pad * 4U; + writew(PINMUX_FUNC_C, reg); + } +} + +/* Iterate over every set bit in pin_mask and call writew(pin_number, addr). + * The apb_gpiov2 SETGPIO/CLRGPIO/TOGGPIO/SETDIR registers are all + * pin-indexed: the written word encodes a pin number, not a bitmask. */ +static void gpio_foreach_pin(uint32_t pin_mask, uintptr_t reg_addr, uint32_t extra_bits) +{ + for (uint32_t pin = 0U; pin < 32U; pin++) + { + if ((pin_mask & (1UL << pin)) != 0U) + { + writew(pin | extra_bits, reg_addr); + } + } +} + +void gpio_init(void) +{ + /* GPIO clocking is handled by platform boot code on CORE-V MCU. */ +} + +void gpio_set_output(uint32_t pin_mask) +{ + /* Route physical pads to the GPIO controller via the pad-mux (FUNC_C). */ + gpio_pinmux_set_func_c(pin_mask); + + /* Configure each pin as push-pull output via SETDIR. */ + gpio_foreach_pin(pin_mask, + (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETDIR_OFFSET), + GPIO_DIR_OUTPUT); +} + +void gpio_toggle(uint32_t pin_mask) +{ + gpio_foreach_pin(pin_mask, + (uintptr_t)(PULP_GPIO_ADDR + GPIO_TOGGPIO_OFFSET), + 0U); +} + +void gpio_set(uint32_t pin_mask) +{ + gpio_foreach_pin(pin_mask, + (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETGPIO_OFFSET), + 0U); +} + +void gpio_clear(uint32_t pin_mask) +{ + gpio_foreach_pin(pin_mask, + (uintptr_t)(PULP_GPIO_ADDR + GPIO_CLRGPIO_OFFSET), + 0U); +} + +void gpio_setpinmux(uint8_t io_pad, uint8_t mux) +{ + uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE + + (uintptr_t)io_pad * 4U; + writew((uint32_t)mux & 0x3U, reg); +} + +uint8_t gpio_getpinmux(uint8_t io_pad) +{ + uintptr_t reg = PULP_APB_SOC_CTRL_ADDR + APB_SOC_PADMUX_BASE + + (uintptr_t)io_pad * 4U; + return (uint8_t)(readw(reg) & 0x3U); +} + +void gpio_pin_set_dir(uint8_t pin, uint8_t dir) +{ + uint32_t val = (uint32_t)pin; + if (dir != 0U) + { + val |= GPIO_DIR_OUTPUT; + } + writew(val, (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETDIR_OFFSET)); +} + +uint32_t gpio_pin_read_status(uint8_t pin) +{ + writew((uint32_t)pin, (uintptr_t)(PULP_GPIO_ADDR + GPIO_SETSEL_OFFSET)); + return readw((uintptr_t)(PULP_GPIO_ADDR + GPIO_RDSTAT_OFFSET)); +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/i2c_master.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/i2c_master.c new file mode 100644 index 00000000..eb1461b9 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/i2c_master.c @@ -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 Copilot (Sonnet 4.6). + * 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 <stddef.h> +#include <stdint.h> + +#include "bits.h" +#include "i2c_master.h" +#include "io.h" +#include "pulp_mem_map.h" + +#define UDMA_I2C_RX_SADDR_OFFSET 0x00U +#define UDMA_I2C_RX_SIZE_OFFSET 0x04U +#define UDMA_I2C_RX_CFG_OFFSET 0x08U +#define UDMA_I2C_TX_SADDR_OFFSET 0x10U +#define UDMA_I2C_TX_SIZE_OFFSET 0x14U +#define UDMA_I2C_TX_CFG_OFFSET 0x18U +#define UDMA_I2C_STATUS_OFFSET 0x20U +#define UDMA_I2C_SETUP_OFFSET 0x24U + +#define UDMA_CTRL_CG_OFFSET 0x00U +#define UDMA_CFG_EN_BIT BIT(4) +#define UDMA_CFG_PENDING_BIT BIT(5) +#define UDMA_I2C_STATUS_AL_BIT BIT(1) +#define UDMA_I2C_SETUP_RESET_BIT BIT(0) +#define I2C_MASTER_COUNT 2U +#define I2C_TIMEOUT_ITERATIONS 1000000U + +#define I2C_CMD_CFG 0xE0U +#define I2C_CMD_START 0x00U +#define I2C_CMD_STOP 0x20U +#define I2C_CMD_RD_ACK 0x40U +#define I2C_CMD_RD_NACK 0x60U +#define I2C_CMD_WR 0x80U +#define I2C_CMD_WAIT 0xA0U +#define I2C_CMD_RPT 0xC0U + +static uint8_t s_cmd_buf[32]; +static uint8_t s_clkdiv[I2C_MASTER_COUNT]; + +static uintptr_t i2c_master_base(uint8_t id) +{ + return (id == 0U) ? (uintptr_t)UDMA_CH_ADDR_I2CM0 : (uintptr_t)UDMA_CH_ADDR_I2CM1; +} + +int i2c_master_init(uint8_t id, uint32_t i2c_freq, uint32_t periph_freq) +{ + uint32_t cg; + uint32_t clk_div; + uintptr_t base; + + if ((id >= I2C_MASTER_COUNT) || (i2c_freq == 0U) || (periph_freq == 0U)) + { + return -1; + } + + cg = readw((uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET)); + cg |= (id == 0U) ? UDMA_CTRL_I2CM0_CLKEN : UDMA_CTRL_I2CM1_CLKEN; + writew(cg, (uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET)); + + clk_div = periph_freq / i2c_freq; + if (clk_div == 0U) + { + clk_div = 1U; + } + else if (clk_div > 255U) + { + clk_div = 255U; + } + s_clkdiv[id] = (uint8_t)clk_div; + + base = i2c_master_base(id); + writew(UDMA_I2C_SETUP_RESET_BIT, base + UDMA_I2C_SETUP_OFFSET); + writew(0U, base + UDMA_I2C_SETUP_OFFSET); + writew(0U, base + UDMA_I2C_RX_CFG_OFFSET); + writew(0U, base + UDMA_I2C_TX_CFG_OFFSET); + + return 0; +} + +int i2c_master_read_reg(uint8_t id, uint8_t dev_addr7, uint8_t reg_addr, + uint8_t *buf, uint8_t len) +{ + uintptr_t base; + uint32_t timeout; + uint32_t cmd_len; + uint32_t status; + + if ((id >= I2C_MASTER_COUNT) || (dev_addr7 > 0x7FU) || (buf == NULL) || (len == 0U)) + { + return -1; + } + + cmd_len = 0U; + s_cmd_buf[cmd_len++] = I2C_CMD_CFG; + s_cmd_buf[cmd_len++] = 0U; + s_cmd_buf[cmd_len++] = s_clkdiv[id]; + s_cmd_buf[cmd_len++] = I2C_CMD_START; + s_cmd_buf[cmd_len++] = I2C_CMD_WR; + s_cmd_buf[cmd_len++] = (uint8_t)(dev_addr7 << 1U); + s_cmd_buf[cmd_len++] = I2C_CMD_WR; + s_cmd_buf[cmd_len++] = reg_addr; + s_cmd_buf[cmd_len++] = I2C_CMD_START; + s_cmd_buf[cmd_len++] = I2C_CMD_WR; + s_cmd_buf[cmd_len++] = (uint8_t)((dev_addr7 << 1U) | 1U); + if (len > 1U) + { + s_cmd_buf[cmd_len++] = I2C_CMD_RPT; + s_cmd_buf[cmd_len++] = (uint8_t)(len - 1U); + s_cmd_buf[cmd_len++] = I2C_CMD_RD_ACK; + } + s_cmd_buf[cmd_len++] = I2C_CMD_RD_NACK; + s_cmd_buf[cmd_len++] = I2C_CMD_STOP; + s_cmd_buf[cmd_len++] = I2C_CMD_WAIT; + s_cmd_buf[cmd_len++] = 0U; + + base = i2c_master_base(id); + writew((uint32_t)(uintptr_t)buf, base + UDMA_I2C_RX_SADDR_OFFSET); + writew((uint32_t)len, base + UDMA_I2C_RX_SIZE_OFFSET); + writew(UDMA_CFG_EN_BIT, base + UDMA_I2C_RX_CFG_OFFSET); + + writew((uint32_t)(uintptr_t)s_cmd_buf, base + UDMA_I2C_TX_SADDR_OFFSET); + writew(cmd_len, base + UDMA_I2C_TX_SIZE_OFFSET); + writew(UDMA_CFG_EN_BIT, base + UDMA_I2C_TX_CFG_OFFSET); + + for (timeout = 0U; timeout < I2C_TIMEOUT_ITERATIONS; ++timeout) + { + status = readw(base + UDMA_I2C_STATUS_OFFSET); + if ((status & UDMA_I2C_STATUS_AL_BIT) != 0U) + { + return -1; + } + if (((readw(base + UDMA_I2C_TX_CFG_OFFSET) & UDMA_CFG_PENDING_BIT) == 0U) && + ((readw(base + UDMA_I2C_RX_CFG_OFFSET) & UDMA_CFG_PENDING_BIT) == 0U)) + { + return 0; + } + } + + return -1; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/irq.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/irq.c new file mode 100644 index 00000000..cb79cc06 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/irq.c @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#include <stdint.h> + +#include "pulp_mem_map.h" +#include "io.h" +#include "irq.h" +#include "csr.h" + +void irq_mask(uint32_t mask) +{ + writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_OFFSET)); +} + +void irq_enable(uint32_t mask) +{ + writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_SET_OFFSET)); +} + +void irq_disable(uint32_t mask) +{ + writew(mask, (uintptr_t)(PULP_FC_IRQ_ADDR + IRQ_REG_MASK_CLEAR_OFFSET)); +} + +uint32_t irq_clint_disable(void) +{ + return (uint32_t)csr_read_clear(CSR_MSTATUS, MSTATUS_IE); +} + +uint32_t irq_clint_enable(void) +{ + return (uint32_t)csr_read_set(CSR_MSTATUS, MSTATUS_IE); +} + +void pulp_irq_init(void) +{ + irq_disable(0xFFFFFFFFUL); +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/string.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/string.c new file mode 100644 index 00000000..7ff699e7 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/string.c @@ -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 Copilot (Sonnet 4.6). + * 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 <stddef.h> +#include <stdint.h> + +#include "string.h" + +void *memcpy(void *dest, const void *src, size_t n) +{ + size_t index; + uint8_t *dst = (uint8_t *)dest; + const uint8_t *source = (const uint8_t *)src; + + for (index = 0U; index < n; ++index) + { + dst[index] = source[index]; + } + + return dest; +} + +void *memset(void *dest, int c, size_t n) +{ + size_t index; + uint8_t *dst = (uint8_t *)dest; + uint8_t value = (uint8_t)c; + + for (index = 0U; index < n; ++index) + { + dst[index] = value; + } + + return dest; +} + +int memcmp(const void *lhs, const void *rhs, size_t n) +{ + size_t index; + const uint8_t *left = (const uint8_t *)lhs; + const uint8_t *right = (const uint8_t *)rhs; + + for (index = 0U; index < n; ++index) + { + if (left[index] != right[index]) + { + return (left[index] < right[index]) ? -1 : 1; + } + } + + return 0; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/system_core_v_mcu.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/system_core_v_mcu.c new file mode 100644 index 00000000..f142c95d --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/system_core_v_mcu.c @@ -0,0 +1,132 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <stddef.h> +#include <stdint.h> + +#include "csr.h" +#include "fll.h" +#include "gpio.h" +#include "irq.h" +#include "properties.h" +#include "system_core_v_mcu.h" +#include "timer_irq.h" +#include "tx_api.h" +#include "uart_driver.h" + +extern void _tx_timer_interrupt(void); + +volatile uint32_t system_core_clock = DEFAULT_SYSTEM_CLOCK; +volatile uint32_t last_trap_mcause; +void (*isr_table[32])(void); + +static uint32_t uart_console_ready; + +static void uart_write_hex32(uint32_t value) +{ + static const char hex[] = "0123456789ABCDEF"; + int shift; + + uart_write_str(0U, "0x"); + for (shift = 28; shift >= 0; shift -= 4) + { + uart_write_byte(0U, (uint8_t)hex[(value >> (uint32_t)shift) & 0xFU]); + } +} + +void tx_undefined_irq_handler(void) +{ + if (uart_console_ready != 0U) + { + uart_write_str(0U, "\r\nUndefined IRQ\r\n"); + } + + /* MISRA deviation: intentional infinite loop used as a fault sink. */ + for (;;) + { + } +} + +void tx_timer_irq_handler(void) +{ + _tx_timer_interrupt(); +} + +void system_init(void) +{ + uint32_t i; + + for (i = 0U; i < 32U; ++i) + { + isr_table[i] = tx_undefined_irq_handler; + } + + isr_table[7U] = tx_timer_irq_handler; + + for (i = 0U; i < ARCHI_NB_FLL; ++i) + { + pi_fll_init((fll_type_t)i, 0U); + } + + pulp_irq_init(); + (void)timer_irq_init(ARCHI_SOC_FREQUENCY / (uint32_t)TX_TIMER_TICKS_PER_SECOND); + /* CV32E40P routes the FC Timer LO to irq_i[7] (MTI, bit 7), which maps + * to mip[7]. IRQ_MASK in cv32e40p_cs_registers forces mie[10] to zero, + * so bit 7 is the correct enable bit. mcause will be 0x80000007. */ + (void)csr_read_set(CSR_MIE, BIT(7)); + + gpio_init(); + if (uart_init(0U, 115200U, ARCHI_FPGA_FREQUENCY) == 0) + { + uart_console_ready = 1U; + } +} + +void tx_trap_handler(uint32_t mcause, uint32_t mepc, uint32_t mtval) +{ + last_trap_mcause = mcause; + + if ((mcause & 0x80000000UL) != 0UL) + { + uint32_t irq_id = mcause & 0x1FUL; + + if (isr_table[irq_id] != NULL) + { + isr_table[irq_id](); + } + else + { + tx_undefined_irq_handler(); + } + } + else + { + if (uart_console_ready != 0U) + { + uart_write_str(0U, "\r\nTrap mcause="); + uart_write_hex32(mcause); + uart_write_str(0U, " mepc="); + uart_write_hex32(mepc); + uart_write_str(0U, " mtval="); + uart_write_hex32(mtval); + uart_write_str(0U, "\r\n"); + } + + /* MISRA deviation: intentional infinite loop used as a fault sink. */ + for (;;) + { + } + } +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/temp_sensor.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/temp_sensor.c new file mode 100644 index 00000000..6d70e943 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/temp_sensor.c @@ -0,0 +1,46 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <stdint.h> + +#include "i2c_master.h" +#include "properties.h" +#include "temp_sensor.h" + +#define ADT7420_I2C_ID 1U +#define ADT7420_ADDR7 0x4BU +#define ADT7420_TEMP_REG 0x00U +#define ADT7420_I2C_FREQ_HZ 200000U + +void temp_sensor_init(void) +{ + (void)i2c_master_init(ADT7420_I2C_ID, ADT7420_I2C_FREQ_HZ, ARCHI_FPGA_FREQUENCY); +} + +int16_t temp_read_celsius_x10(void) +{ + uint8_t buf[2]; + int16_t raw; + int16_t value; + + if (i2c_master_read_reg(ADT7420_I2C_ID, ADT7420_ADDR7, ADT7420_TEMP_REG, &buf[0], 2U) != 0) + { + return INT16_MIN; + } + + raw = (int16_t)(((uint16_t)buf[0] << 8U) | (uint16_t)buf[1]); + value = (int16_t)(raw >> 3); + return (int16_t)(((int32_t)value * 5) / 8); +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/timer_irq.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/timer_irq.c new file mode 100644 index 00000000..9a085d9f --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/timer_irq.c @@ -0,0 +1,58 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#include <stdint.h> + +#include "pulp_mem_map.h" +#include "io.h" +#include "timer.h" +#include "timer_irq.h" + +static uint32_t last_count; + +int timer_irq_init(uint32_t ticks) +{ + (void)timer_irq_set_timeout(ticks); + + writew(TIMER_CFG_LO_ENABLE_MASK | + TIMER_CFG_LO_RESET_MASK | + TIMER_CFG_LO_MODE_MASK | + TIMER_CFG_LO_IRQEN_MASK, + (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_LO_OFFSET)); + + last_count = 0U; + return 0; +} + +int timer_irq_set_timeout(uint32_t ticks) +{ + writew(1U, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_RESET_LO_OFFSET)); + writew(ticks, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CMP_LO_OFFSET)); + last_count = 0U; + return 0; +} + +uint32_t timer_irq_clock_elapsed(void) +{ + uint32_t current = timer_irq_cycle_get_32(); + uint32_t elapsed = current - last_count; + + last_count = current; + return elapsed; +} + +uint32_t timer_irq_cycle_get_32(void) +{ + return readw((uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CNT_LO_OFFSET)); +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/uart_driver.c b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/uart_driver.c new file mode 100644 index 00000000..33b1ff15 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/bsp/uart_driver.c @@ -0,0 +1,169 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <stddef.h> +#include <stdint.h> + +#include "bits.h" +#include "io.h" +#include "pulp_mem_map.h" +#include "uart_driver.h" + +#define UDMA_CTRL_CG_OFFSET 0x00U +#define UDMA_CTRL_UART0_CLKEN BIT(0) + +#define UDMA_UART_RX_SADDR_OFFSET 0x00U +#define UDMA_UART_RX_SIZE_OFFSET 0x04U +#define UDMA_UART_RX_CFG_OFFSET 0x08U +#define UDMA_UART_TX_SADDR_OFFSET 0x10U +#define UDMA_UART_TX_SIZE_OFFSET 0x14U +#define UDMA_UART_TX_CFG_OFFSET 0x18U +#define UDMA_UART_STATUS_OFFSET 0x20U +#define UDMA_UART_SETUP_OFFSET 0x24U +#define UDMA_UART_VALID_OFFSET 0x30U +#define UDMA_UART_DATA_OFFSET 0x34U + +#define UDMA_CFG_EN_BIT BIT(4) +/* EN (bit 4) only; DATASIZE=0 for 8-bit transfers; 0x12 would set DATASIZE=1 + * (16-bit) and cause the EN bit to never clear for single-byte buffers. */ +#define UDMA_UART_TX_CFG_ENABLE 0x10U +#define UDMA_UART_WORDLEN_8_BITS 3U +#define UDMA_UART_TX_ENABLE_BIT BIT(8) +#define UDMA_UART_RX_ENABLE_BIT BIT(9) +#define UDMA_UART_RX_POLLING_BIT BIT(4) +#define UDMA_UART_RX_CLEAN_BIT BIT(5) +#define UDMA_UART_DIV_SHIFT 16U +#define UDMA_UART_VALID_DATA_BIT BIT(0) +#define UDMA_UART_STATUS_TX_BUSY BIT(0) +#define UDMA_UART_MAX_TRANSFER 0xFFFFU + +static uint8_t uart_tx_byte[N_UART]; + +static uintptr_t uart_base(uint8_t uart_id) +{ + return (uintptr_t)(UDMA_CH_ADDR_UART + ((uintptr_t)uart_id * (uintptr_t)UDMA_CH_SIZE)); +} + +int uart_init(uint8_t uart_id, uint32_t baudrate, uint32_t periph_freq) +{ + uint32_t clk_div; + uint32_t setup; + uint32_t cg; + + if ((uart_id >= N_UART) || (baudrate == 0U) || (periph_freq == 0U)) + { + return -1; + } + + cg = readw((uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET)); + cg |= (uint32_t)(UDMA_CTRL_UART0_CLKEN << uart_id); + writew(cg, (uintptr_t)(UDMA_CH_ADDR_CTRL + UDMA_CTRL_CG_OFFSET)); + + clk_div = periph_freq / baudrate; + if (clk_div == 0U) + { + clk_div = 1U; + } + + setup = (clk_div << UDMA_UART_DIV_SHIFT) | + UDMA_UART_TX_ENABLE_BIT | + UDMA_UART_RX_ENABLE_BIT | + UDMA_UART_RX_POLLING_BIT | + UDMA_UART_RX_CLEAN_BIT | + (UDMA_UART_WORDLEN_8_BITS << 1U); + writew(setup, uart_base(uart_id) + UDMA_UART_SETUP_OFFSET); + + writew(0U, uart_base(uart_id) + UDMA_UART_RX_SADDR_OFFSET); + writew(0U, uart_base(uart_id) + UDMA_UART_RX_SIZE_OFFSET); + writew(0U, uart_base(uart_id) + UDMA_UART_RX_CFG_OFFSET); + + return 0; +} + +void uart_write_byte(uint8_t uart_id, uint8_t c) +{ + if (uart_id >= N_UART) + { + return; + } + + uart_tx_byte[uart_id] = c; + uart_write_buf(uart_id, &uart_tx_byte[uart_id], 1U); +} + +int uart_read_byte(uint8_t uart_id) +{ + if (uart_id >= N_UART) + { + return -1; + } + + if ((readw(uart_base(uart_id) + UDMA_UART_VALID_OFFSET) & UDMA_UART_VALID_DATA_BIT) == 0U) + { + return -1; + } + + return (int)(readw(uart_base(uart_id) + UDMA_UART_DATA_OFFSET) & 0xFFU); +} + +void uart_write_str(uint8_t uart_id, const char *str) +{ + if (str == NULL) + { + return; + } + + while (*str != '\0') + { + uart_write_byte(uart_id, (uint8_t)*str); + ++str; + } +} + +void uart_write_buf(uint8_t uart_id, const uint8_t *buf, uint32_t len) +{ + uintptr_t base_addr; + const uint8_t *current; + uint32_t remaining; + + if ((uart_id >= N_UART) || (buf == NULL) || (len == 0U)) + { + return; + } + + base_addr = uart_base(uart_id); + current = buf; + remaining = len; + + while (remaining > 0U) + { + uint32_t chunk = (remaining > UDMA_UART_MAX_TRANSFER) ? UDMA_UART_MAX_TRANSFER : remaining; + + while ((readw(base_addr + UDMA_UART_STATUS_OFFSET) & UDMA_UART_STATUS_TX_BUSY) != 0U) + { + } + + writew((uint32_t)(uintptr_t)current, base_addr + UDMA_UART_TX_SADDR_OFFSET); + writew(chunk, base_addr + UDMA_UART_TX_SIZE_OFFSET); + writew(UDMA_UART_TX_CFG_ENABLE, base_addr + UDMA_UART_TX_CFG_OFFSET); + + while ((readw(base_addr + UDMA_UART_TX_CFG_OFFSET) & UDMA_CFG_EN_BIT) != 0U) + { + } + + current += chunk; + remaining -= chunk; + } +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh b/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh new file mode 100755 index 00000000..b610ac42 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash +############################################################################## +# 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 +############################################################################## + +set -e + +XPACK_GCC_DIR=/opt/xpack-riscv-none-elf-gcc-15.2.0-1 +if [ -d "${XPACK_GCC_DIR}/bin" ]; then + export PATH="${XPACK_GCC_DIR}/bin:${PATH}" +fi + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +THREADX_ROOT="${SCRIPT_DIR}/../../../../.." +cmake -B "${SCRIPT_DIR}/build" \ + -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake" \ + "${SCRIPT_DIR}" +cmake --build "${SCRIPT_DIR}/build" diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/crt0.S b/ports/risc-v32/gnu/example_build/core_v_mcu/crt0.S new file mode 100644 index 00000000..3c761bbe --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/crt0.S @@ -0,0 +1,48 @@ +/***************************************************************************/ +/* Copyright 2020 ETH Zurich + * Copyright (c) 2017 SiFive Inc. All rights reserved. + * Copyright (c) 2019 ETH Zürich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0 (Apache-2.0) + * or the BSD 2-Clause License (BSD-2-Clause) at your option. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: (Apache-2.0 OR BSD-2-Clause) AND MIT + ***************************************************************************/ + + .section .text.start + .global _start + .type _start, @function + +_start: + .option push + .option norelax +1: auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) + .option pop + + la sp, __stack_top + + la a0, __vector_start + ori a0, a0, 1 + csrw mtvec, a0 + + la t0, __bss_start + la t1, __bss_end +2: + bgeu t0, t1, 3f + sw zero, 0(t0) + addi t0, t0, 4 + j 2b +3: + call main +4: + wfi + j 4b + + .size _start, .-_start diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/demo_threadx.c b/ports/risc-v32/gnu/example_build/core_v_mcu/demo_threadx.c new file mode 100644 index 00000000..c7daac3c --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/demo_threadx.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <stdint.h> + +#include "gpio.h" +#include "system_core_v_mcu.h" +#include "tx_api.h" +#include "uart_driver.h" + +#define DEMO_STACK_SIZE 1024U +#define DEMO_BYTE_POOL_SIZE 4096U +/* + * LED[0] on Nexys A7 = IO pad 11 = GPIO/apbio pin 4 (MUX=2). + * Verified in the quick-start guide and the 2022 nexys-pin-table.csv used to + * synthesise the pre-built bitfile (io_pad = gpio_pin + 7). + */ +#define DEMO_LED_PIN 4U +#define DEMO_LED_MASK (1UL << DEMO_LED_PIN) + +/* Assemble the version banner string at compile time from tx_api.h constants. */ +#define _TX_STR(x) #x +#define TX_STR(x) _TX_STR(x) +#define TX_VERSION_STRING \ + "v" TX_STR(THREADX_MAJOR_VERSION) \ + "." TX_STR(THREADX_MINOR_VERSION) \ + "." TX_STR(THREADX_PATCH_VERSION) \ + "." TX_STR(THREADX_BUILD_VERSION) + +static const char banner[] = + "\r\nEclipse ThreadX for OpenHW CORE-V MCU " TX_VERSION_STRING "\r\n" + "Copyright (c) 2026 Eclipse ThreadX Contributors\r\n\r\n"; + +static TX_THREAD blinky_thread; +static TX_THREAD uart_thread; +static TX_BYTE_POOL byte_pool; +static uint8_t memory_area[DEMO_BYTE_POOL_SIZE]; + +static void demo_error_loop(void) +{ + /* MISRA deviation: intentional infinite loop used as a fault sink. */ + for (;;) + { + } +} + +static void blinky_thread_entry(ULONG arg) +{ + TX_PARAMETER_NOT_USED(arg); + + /* Configure LED[0] as push-pull output (sets pad-mux to FUNC_C = 2). */ + gpio_set_output((uint32_t)DEMO_LED_MASK); + + for (;;) + { + gpio_set((uint32_t)DEMO_LED_MASK); + tx_thread_sleep(100U); /* 1 s on (100 ticks × 10 ms) */ + gpio_clear((uint32_t)DEMO_LED_MASK); + tx_thread_sleep(100U); /* 1 s off */ + } +} + +static void uart_thread_entry(ULONG arg) +{ + TX_PARAMETER_NOT_USED(arg); + + uart_write_str(0U, banner); + for (;;) + { + uart_write_str(0U, "."); + tx_thread_sleep(100U); + } +} + +void tx_application_define(void *first_unused_memory) +{ + CHAR *stack_ptr = TX_NULL; + UINT status; + + TX_PARAMETER_NOT_USED(first_unused_memory); + + status = tx_byte_pool_create(&byte_pool, "demo pool", memory_area, DEMO_BYTE_POOL_SIZE); + if (status != TX_SUCCESS) + { + demo_error_loop(); + } + + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT); + if (status != TX_SUCCESS) + { + demo_error_loop(); + } + + status = tx_thread_create(&blinky_thread, "blinky", blinky_thread_entry, 0U, + stack_ptr, DEMO_STACK_SIZE, 1U, 1U, + TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + demo_error_loop(); + } + + status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT); + if (status != TX_SUCCESS) + { + demo_error_loop(); + } + + status = tx_thread_create(&uart_thread, "uart", uart_thread_entry, 0U, + stack_ptr, DEMO_STACK_SIZE, 2U, 2U, + TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + demo_error_loop(); + } +} + +int main(void) +{ + system_init(); + tx_kernel_enter(); + return 0; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/deploy.sh b/ports/risc-v32/gnu/example_build/core_v_mcu/deploy.sh new file mode 100755 index 00000000..2e22ec1e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/deploy.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env 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 Copilot (Sonnet 4.6). +# * The AI-generated portions may be considered public domain (CC0-1.0) +# * and not subject to the project's licence. +# * +# * SPDX-License-Identifier: MIT AND CC0-1.0 +# ***************************************************************************/ + +# deploy.sh -- build (optionally), flash, and run/debug the CORE-V MCU target +# via the Ashling Opella LD debug probe. +# +# Usage: +# bash deploy.sh [options] +# +# Options: +# --build Run build.sh before flashing (default: skip). +# --debug After loading, stop at main and leave GDB attached +# (default: run free and exit GDB). +# --elf <path> Override the ELF to flash +# (default: build/demo_threadx.elf). +# --openocd-cfg <p> Override the OpenOCD config file. +# +# Prerequisites: +# * riscv64-unknown-elf-gdb and openocd must be on PATH. +# * Run setup_opella.sh once to configure udev rules. +# * The Nexys A7 board must be powered on. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Prefer a bare-metal RISC-V GDB; fall back to gdb-multiarch (Ubuntu apt default) +if command -v riscv64-unknown-elf-gdb >/dev/null 2>&1; then + GDB="riscv64-unknown-elf-gdb" +elif command -v gdb-multiarch >/dev/null 2>&1; then + GDB="gdb-multiarch" +else + GDB="riscv64-unknown-elf-gdb" # will produce a clear error below +fi +OPENOCD_LOG="/tmp/openocd_demo_threadx.log" +OPENOCD_PID="" +OPENOCD_TIMEOUT=10 + +DEFAULT_ELF="${SCRIPT_DIR}/build/demo_threadx.elf" +DEFAULT_CFG="${SCRIPT_DIR}/openocd-nexys-Ashling-Opella-LD.cfg" + +OPT_BUILD=0 +OPT_DEBUG=0 +OPT_ELF="" +OPT_CFG="" + +usage() { grep '^# ' "$0" | sed 's/^# //' | head -30; exit 0; } + +while [[ $# -gt 0 ]]; do + case "$1" in + --build) OPT_BUILD=1; shift ;; + --debug) OPT_DEBUG=1; shift ;; + --elf) OPT_ELF="$2"; shift 2 ;; + --openocd-cfg) OPT_CFG="$2"; shift 2 ;; + -h|--help) usage ;; + *) echo "[ERROR] Unknown option: $1" >&2; usage ;; + esac +done + +ELF="${OPT_ELF:-${DEFAULT_ELF}}" +CFG="${OPT_CFG:-${DEFAULT_CFG}}" + +info() { echo "[INFO] $*"; } +die() { echo "[ERROR] $*" >&2; exit 1; } + +stop_openocd() { + if [ -n "${OPENOCD_PID}" ] && kill -0 "${OPENOCD_PID}" 2>/dev/null; then + info "Stopping OpenOCD (PID ${OPENOCD_PID}) ..." + kill "${OPENOCD_PID}" 2>/dev/null || true + wait "${OPENOCD_PID}" 2>/dev/null || true + fi +} + +trap stop_openocd EXIT INT TERM + +if [ "${OPT_BUILD}" -eq 1 ]; then + info "Running build.sh ..." + bash "${SCRIPT_DIR}/build.sh" +fi + +[ -f "${ELF}" ] || die "ELF not found: ${ELF} (run with --build to build first)" +[ -f "${CFG}" ] || die "OpenOCD config not found: ${CFG}" +command -v openocd >/dev/null 2>&1 || die "openocd not found on PATH" +command -v "${GDB}" >/dev/null 2>&1 || die "${GDB} not found on PATH" + +info "Starting OpenOCD with config: ${CFG}" +info "Log: ${OPENOCD_LOG}" +openocd -f "${CFG}" >"${OPENOCD_LOG}" 2>&1 & +OPENOCD_PID=$! + +info "Waiting for OpenOCD to be ready (up to ${OPENOCD_TIMEOUT}s) ..." +ELAPSED=0 +while ! grep -q "Ready for Remote Connections" "${OPENOCD_LOG}" 2>/dev/null; do + sleep 1 + ELAPSED=$((ELAPSED + 1)) + if [ "${ELAPSED}" -ge "${OPENOCD_TIMEOUT}" ]; then + echo "--- OpenOCD log ---" && cat "${OPENOCD_LOG}" + die "OpenOCD did not become ready within ${OPENOCD_TIMEOUT}s" + fi + if ! kill -0 "${OPENOCD_PID}" 2>/dev/null; then + echo "--- OpenOCD log ---" && cat "${OPENOCD_LOG}" + die "OpenOCD exited unexpectedly" + fi +done +info "OpenOCD is ready." + +GDB_INIT_FILE="/tmp/gdb_deploy_demo_threadx.gdb" +printf 'set confirm off +set remotetimeout 60 +file %s +target extended-remote localhost:3333 +load +' "${ELF}" > "${GDB_INIT_FILE}" + +if [ "${OPT_DEBUG}" -eq 0 ]; then + info "Flashing and running (detached) ..." + printf 'monitor resume\ndisconnect\nquit\n' >> "${GDB_INIT_FILE}" + info "ELF: ${ELF}" + riscv64-unknown-elf-size "${ELF}" + "${GDB}" --batch --command="${GDB_INIT_FILE}" 2>&1 \ + | grep -v "keep_alive() was not invoked" \ + | grep -v "GDB alive packet not sent" + info "Flash complete. Application is running on the target." + info "Serial console: minicom -b 115200 -D /dev/ttyUSBx" +else + info "Flashing and stopping at main for interactive debug ..." + printf 'break main\ncontinue\n' >> "${GDB_INIT_FILE}" + info "ELF: ${ELF}" + riscv64-unknown-elf-size "${ELF}" + "${GDB}" --command="${GDB_INIT_FILE}" +fi diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/gdb_init b/ports/risc-v32/gnu/example_build/core_v_mcu/gdb_init new file mode 100644 index 00000000..718a20f1 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/gdb_init @@ -0,0 +1,6 @@ +set arch riscv:rv32 +target extended-remote localhost:3333 +file build/demo_threadx.elf +load +break main +continue diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/bits.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/bits.h new file mode 100644 index 00000000..08871387 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/bits.h @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* Copyright (c) 2011-2014, Wind River Systems, Inc. + * Copyright 2020 ETH Zurich + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef BITS_H +#define BITS_H + +#include <stdbool.h> +#include <stdint.h> + +/* Helper to pass an integer as a pointer or vice versa. */ +#define POINTER_TO_UINT(x) ((uintptr_t)(x)) +#define UINT_TO_POINTER(x) ((void *)(uintptr_t)(x)) +#define POINTER_TO_INT(x) ((intptr_t)(x)) +#define INT_TO_POINTER(x) ((void *)(intptr_t)(x)) + +#if !(defined(__CHAR_BIT__) && defined(__SIZEOF_LONG__)) +#error Missing required predefined macros for BITS_PER_LONG calculation +#endif + +#define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1UL) & (~0UL >> (BITS_PER_LONG - 1UL - (h)))) + +#define KB(x) ((x) << 10) +#define MB(x) (KB(x) << 10) +#define GB(x) (MB(x) << 10) + +#define KHZ(x) ((x) * 1000) +#define MHZ(x) (KHZ(x) * 1000) + +#ifndef BIT +#ifdef _ASMLANGUAGE +#define BIT(n) (1 << (n)) +#else +#define BIT(n) (1UL << (n)) +#endif +#endif + +#define WRITE_BIT(var, bit, set) \ + ((var) = ((set) != 0) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit))) + +#define BIT_MASK(n) (BIT(n) - 1UL) + +#define REG_SET(FIELD, v) (((uint32_t)(v) << FIELD##_SHIFT) & FIELD##_MASK) +#define REG_GET(FIELD, v) (((uint32_t)(v) & FIELD##_MASK) >> FIELD##_SHIFT) + +#endif /* BITS_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/csr.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/csr.h new file mode 100644 index 00000000..69c7763e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/csr.h @@ -0,0 +1,75 @@ +/***************************************************************************/ +/* Copyright (C) 2020 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef CSR_H +#define CSR_H + +#include "bits.h" + +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3A0 +#define CSR_PMPADDR0 0x3B0 +#define CSR_MVENDORID 0xF11 +#define CSR_MARCHID 0xF12 +#define CSR_MIMPID 0xF13 +#define CSR_MHARTID 0xF14 + +#define MSTATUS_IE BIT(3) + +#define __CSR_EXPAND(x) #x + +#ifndef csr_read +#define csr_read(csr) \ + ({ \ + register unsigned long __val; \ + __asm__ volatile("csrr %0, " __CSR_EXPAND(csr) : "=r"(__val) : : "memory"); \ + __val; \ + }) +#endif + +#ifndef csr_write +#define csr_write(csr, val) \ + ({ \ + unsigned long __val = (unsigned long)(val); \ + __asm__ volatile("csrw " __CSR_EXPAND(csr) ", %0" : : "rK"(__val) : "memory"); \ + }) +#endif + +#ifndef csr_read_clear +#define csr_read_clear(csr, val) \ + ({ \ + unsigned long __val = (unsigned long)(val); \ + __asm__ volatile("csrrc %0, " __CSR_EXPAND(csr) ", %1" : "=r"(__val) : "rK"(__val) : "memory"); \ + __val; \ + }) +#endif + +#ifndef csr_read_set +#define csr_read_set(csr, val) \ + ({ \ + unsigned long __val = (unsigned long)(val); \ + __asm__ volatile("csrrs %0, " __CSR_EXPAND(csr) ", %1" : "=r"(__val) : "rK"(__val) : "memory"); \ + __val; \ + }) +#endif + +#endif /* CSR_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/fll.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/fll.h new file mode 100644 index 00000000..011268df --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/fll.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* Copyright 2020 GreenWaves Technologies + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef FLL_H +#define FLL_H + +#include <stdint.h> + +#include "properties.h" +#include "pulp_mem_map.h" + +#define FLL_STATUS_OFFSET 0x000U +#define FLL_CONF1_OFFSET 0x004U +#define FLL_CONF2_OFFSET 0x008U +#define FLL_INTEGRATOR_OFFSET 0x00CU + +typedef struct +{ + volatile uint32_t FLL_STATUS; + volatile uint32_t FLL_CONF1; + volatile uint32_t FLL_CONF2; + volatile uint32_t FLL_INTEGRATOR; +} fll_ctrl_t; + +typedef enum _fll_type +{ + FLL_SOC = 0, + FLL_PERI = 1, + FLL_CLUSTER = 2 +} fll_type_t; + +typedef enum +{ + PI_FREQ_DOMAIN_FC = 0, + PI_FREQ_DOMAIN_CL = 1, + PI_FREQ_DOMAIN_PERIPH = 2 +} pi_freq_domain_e; + +#define FLL_CTRL_STATUS_MULTI_FACTOR_MASK 0xFFFFU +#define FLL_CTRL_STATUS_MULTI_FACTOR_SHIFT 0U +#define FLL_CTRL_CONF1_MULTI_FACTOR_MASK 0xFFFFU +#define FLL_CTRL_CONF1_MULTI_FACTOR_SHIFT 0U +#define FLL_CTRL_CONF1_DCO_INPUT_MASK 0x03FF0000U +#define FLL_CTRL_CONF1_DCO_INPUT_SHIFT 16U +#define FLL_CTRL_CONF1_CLK_OUT_DIV_MASK 0x3C000000U +#define FLL_CTRL_CONF1_CLK_OUT_DIV_SHIFT 26U +#define FLL_CTRL_CONF1_OUTPUT_LOCK_EN_MASK 0x40000000U +#define FLL_CTRL_CONF1_OUTPUT_LOCK_EN_SHIFT 30U +#define FLL_CTRL_CONF1_MODE_MASK 0x80000000U +#define FLL_CTRL_CONF1_MODE_SHIFT 31U +#define FLL_CTRL_CONF2_LOOPGAIN_MASK 0xFU +#define FLL_CTRL_CONF2_LOOPGAIN_SHIFT 0U +#define FLL_CTRL_CONF2_DEASSERT_CYCLES_MASK 0x3F0U +#define FLL_CTRL_CONF2_DEASSERT_CYCLES_SHIFT 4U +#define FLL_CTRL_CONF2_ASSERT_CYCLES_MASK 0xFC00U +#define FLL_CTRL_CONF2_ASSERT_CYCLES_SHIFT 10U +#define FLL_CTRL_CONF2_LOCK_TOLERANCE_MASK 0x0FFF0000U +#define FLL_CTRL_CONF2_LOCK_TOLERANCE_SHIFT 16U +#define FLL_CTRL_CONF2_CONF_CLK_SEL_MASK 0x20000000U +#define FLL_CTRL_CONF2_CONF_CLK_SEL_SHIFT 29U +#define FLL_CTRL_CONF2_OPEN_LOOP_MASK 0x40000000U +#define FLL_CTRL_CONF2_OPEN_LOOP_SHIFT 30U +#define FLL_CTRL_CONF2_DITHERING_MASK 0x80000000U +#define FLL_CTRL_CONF2_DITHERING_SHIFT 31U +#define FLL_CTRL_INTEGRATOR_FRACT_PART_MASK 0x0000FFC0U +#define FLL_CTRL_INTEGRATOR_FRACT_PART_SHIFT 6U +#define FLL_CTRL_INTEGRATOR_INT_PART_MASK 0x03FF0000U +#define FLL_CTRL_INTEGRATOR_INT_PART_SHIFT 16U +#define FLL_CTRL_SOC_FLL_CONV_MASK 0x1U +#define FLL_CTRL_SOC_FLL_CONV_SHIFT 0U +#define FLL_CTRL_CLUSTER_FLL_CONV_MASK 0x2U +#define FLL_CTRL_CLUSTER_FLL_CONV_SHIFT 1U + +#define FLL_NUM ARCHI_NB_FLL +#define FLL_REF_CLK ARCHI_REF_CLOCK +#define FLL_CTRL ((volatile fll_ctrl_t *)PULP_FLL_ADDR) + +void pi_fll_init(fll_type_t which_fll, uint32_t ret_state); +int pi_fll_set_frequency(fll_type_t which_fll, uint32_t frequency, int check); +int pi_fll_get_frequency(fll_type_t which_fll, uint8_t real); + +#endif /* FLL_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/gpio.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/gpio.h new file mode 100644 index 00000000..da5f6008 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/gpio.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 GPIO_H +#define GPIO_H + +#include <stdint.h> + +/* apb_gpiov2 register map (pin-indexed interface) + * + * Offset Name Access Description + * 0x000 SETGPIO W PWDATA[6:0] = pin number → drive pin high + * 0x004 CLRGPIO W PWDATA[6:0] = pin number → drive pin low + * 0x008 TOGGPIO W PWDATA[6:0] = pin number → toggle pin + * 0x010 PIN0 R bits [31:0] = sampled input state of pins 0-31 + * 0x020 OUT0 R/W bits [31:0] = output state bitmask, pins 0-31 + * 0x030 SETSEL W select pin for RDSTAT + * 0x034 RDSTAT R status of selected pin + * 0x038 SETDIR W PWDATA[6:0]=pin, PWDATA[25:24]=dir + * dir[0]=1 → push-pull output; dir[1]=1 → open-drain + * 0x03C SETINT W interrupt configuration + * 0x040 INTACK W interrupt acknowledge + */ +#define GPIO_SETGPIO_OFFSET 0x000U +#define GPIO_CLRGPIO_OFFSET 0x004U +#define GPIO_TOGGPIO_OFFSET 0x008U +#define GPIO_PIN0_OFFSET 0x010U +#define GPIO_OUT0_OFFSET 0x020U +#define GPIO_SETSEL_OFFSET 0x030U +#define GPIO_RDSTAT_OFFSET 0x034U +#define GPIO_SETDIR_OFFSET 0x038U +#define GPIO_SETINT_OFFSET 0x03CU +#define GPIO_INTACK_OFFSET 0x040U + +/* Direction field in SETDIR: bits [25:24] of the written word. + * 0b01 = push-pull output enable; 0b10 = open-drain; 0b00 = input */ +#define GPIO_DIR_OUTPUT (1U << 24U) + +void gpio_init(void); +void gpio_set_output(uint32_t pin_mask); +void gpio_toggle(uint32_t pin_mask); +void gpio_set(uint32_t pin_mask); +void gpio_clear(uint32_t pin_mask); + +/* Pad-mux control (APB SOC CTRL v1.0.0). + * Each IO pad has a 32-bit register at SOC_CTRL_BASE + 0x400 + pad*4. + * bits[1:0] = mux function: 0=sys, 1=perio, 2=apbio/GPIO, 3=fpgaio. */ +void gpio_setpinmux(uint8_t io_pad, uint8_t mux); +uint8_t gpio_getpinmux(uint8_t io_pad); + +/* Single-pin direction and status (for CLI use). + * dir: 0 = input, 1 = push-pull output. */ +void gpio_pin_set_dir(uint8_t pin, uint8_t dir); +uint32_t gpio_pin_read_status(uint8_t pin); + +#endif /* GPIO_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/i2c_master.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/i2c_master.h new file mode 100644 index 00000000..4a478b30 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/i2c_master.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 I2C_MASTER_H +#define I2C_MASTER_H + +#include <stdint.h> + +/* i2c_master_init: enable I2C channel clock gate, configure clock divider. + * id: 0 or 1 (I2CM0 or I2CM1) + * i2c_freq: desired I2C clock in Hz (e.g. 200000) + * periph_freq: UDMA peripheral clock in Hz (5000000 on CORE-V FPGA) + * Returns 0 on success, -1 on bad params. */ +int i2c_master_init(uint8_t id, uint32_t i2c_freq, uint32_t periph_freq); + +/* i2c_master_read_reg: read len bytes from register reg_addr of 7-bit addressed device. + * id: I2CM channel (0 or 1) + * dev_addr7: 7-bit I2C device address + * reg_addr: register address to read from + * buf: output buffer (must be in RAM, not stack if possible) + * len: number of bytes to read (1..255) + * Returns 0 on success, -1 on timeout or arbitration loss. */ +int i2c_master_read_reg(uint8_t id, uint8_t dev_addr7, uint8_t reg_addr, + uint8_t *buf, uint8_t len); + +#endif /* I2C_MASTER_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/io.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/io.h new file mode 100644 index 00000000..02364544 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/io.h @@ -0,0 +1,61 @@ +/***************************************************************************/ +/* Copyright 2020 ETH Zurich + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef IO_H +#define IO_H + +#include <stdint.h> + +#ifndef CORE_V_MCU_MMIO_MOCK +static inline void writeb(uint8_t val, uintptr_t addr) +{ + __asm__ volatile("sb %0, 0(%1)" : : "r"(val), "r"((volatile uint8_t *)addr)); +} + +static inline void writeh(uint16_t val, uintptr_t addr) +{ + __asm__ volatile("sh %0, 0(%1)" : : "r"(val), "r"((volatile uint16_t *)addr)); +} + +static inline void writew(uint32_t val, uintptr_t addr) +{ + __asm__ volatile("sw %0, 0(%1)" : : "r"(val), "r"((volatile uint32_t *)addr)); +} + +static inline uint8_t readb(const uintptr_t addr) +{ + uint8_t val; + + __asm__ volatile("lb %0, 0(%1)" : "=r"(val) : "r"((const volatile uint8_t *)addr)); + return val; +} + +static inline uint16_t readh(const uintptr_t addr) +{ + uint16_t val; + + __asm__ volatile("lh %0, 0(%1)" : "=r"(val) : "r"((const volatile uint16_t *)addr)); + return val; +} + +static inline uint32_t readw(const uintptr_t addr) +{ + uint32_t val; + + __asm__ volatile("lw %0, 0(%1)" : "=r"(val) : "r"((const volatile uint32_t *)addr)); + return val; +} +#endif /* CORE_V_MCU_MMIO_MOCK */ + +#endif /* IO_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/irq.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/irq.h new file mode 100644 index 00000000..aafe6226 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/irq.h @@ -0,0 +1,64 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef IRQ_H +#define IRQ_H + +#include "pulp_mem_map.h" +#include "io.h" +#include "bits.h" + +#define IRQ_REG_MASK_OFFSET 0x000U +#define IRQ_REG_MASK_SET_OFFSET 0x004U +#define IRQ_REG_MASK_CLEAR_OFFSET 0x008U +#define IRQ_REG_INT_OFFSET 0x00CU +#define IRQ_REG_INT_SET_OFFSET 0x010U +#define IRQ_REG_INT_CLEAR_OFFSET 0x014U +#define IRQ_REG_ACK_OFFSET 0x018U +#define IRQ_REG_ACK_SET_OFFSET 0x01CU +#define IRQ_REG_ACK_CLEAR_OFFSET 0x020U +#define IRQ_REG_FIFO_OFFSET 0x024U + +#define IRQ_FC_EVT_SW0 BIT(0) +#define IRQ_FC_EVT_SW1 BIT(1) +#define IRQ_FC_EVT_SW2 BIT(2) +#define IRQ_FC_EVT_SW3 BIT(3) +#define IRQ_FC_EVT_SW4 BIT(4) +#define IRQ_FC_EVT_SW5 BIT(5) +#define IRQ_FC_EVT_SW6 BIT(6) +#define IRQ_FC_EVT_SW7 BIT(7) +#define IRQ_FC_EVT_DMA_PE_EVT BIT(8) +#define IRQ_FC_EVT_DMA_PE_IRQ BIT(9) +#define IRQ_FC_EVT_TIMER0_LO BIT(10) +#define IRQ_FC_EVT_TIMER0_HI BIT(11) +#define IRQ_FC_EVT_PF BIT(12) +#define IRQ_FC_EVT_CLK_REF BIT(14) +#define IRQ_FC_EVT_GPIO BIT(15) +#define IRQ_FC_EVT_ADV_TIMER0 BIT(17) +#define IRQ_FC_EVT_ADV_TIMER1 BIT(18) +#define IRQ_FC_EVT_ADV_TIMER2 BIT(19) +#define IRQ_FC_EVT_ADV_TIMER3 BIT(20) +#define IRQ_FC_EVT_SOC_EVT BIT(26) +#define IRQ_FC_EVT_QUIRQE_ERROR BIT(29) +#define IRQ_FC_EVT_PERIPH0 BIT(30) +#define IRQ_FC_EVT_PERIPH1 BIT(31) + +void irq_mask(uint32_t mask); +void irq_enable(uint32_t mask); +void irq_disable(uint32_t mask); +uint32_t irq_clint_disable(void); +uint32_t irq_clint_enable(void); +void pulp_irq_init(void); + +#endif /* IRQ_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/memory_map.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/memory_map.h new file mode 100644 index 00000000..f3048367 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/memory_map.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich, University of Bologna and GreenWaves Technologies + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef MEMORY_MAP_H +#define MEMORY_MAP_H + +#include "pulp_mem_map.h" + +#define L2_BASE 0x1C000000UL +#define L2_SIZE 0x80000UL +#define L2_SHARED_ADDR L2_BASE +#define L2_SHARED_SIZE L2_SIZE +#define ROM_ADDR 0x1A000000UL +#define ROM_SIZE 0x00002000UL + +#define SOC_PERIPHERALS_ADDR PULP_SOC_PERIPHERALS_ADDR +#define SOC_FLL_ADDR PULP_FLL_ADDR +#define GPIO_ADDR PULP_GPIO_ADDR +#define UDMA_CTRL_ADDR PULP_UDMA_ADDR +#define APB_SOC_CTRL_ADDR PULP_APB_SOC_CTRL_ADDR +#define ADV_TIMER_ADDR PULP_ADV_TIMER_ADDR +#define SOC_EU_ADDR PULP_SOC_EU_ADDR +#define FC_IRQ_ADDR PULP_FC_IRQ_ADDR +#define FC_TIMER_ADDR PULP_FC_TIMER_ADDR +#define FC_HWPE_ADDR PULP_FC_HWPE_ADDR +#define STDOUT_ADDR PULP_STDOUT_ADDR + +#endif /* MEMORY_MAP_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/properties.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/properties.h new file mode 100644 index 00000000..98473696 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/properties.h @@ -0,0 +1,43 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich, University of Bologna and GreenWaves Technologies + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef PROPERTIES_H +#define PROPERTIES_H + +#define PULP + +/* Peripheral bus clock (clk_per): PER_CLK_PERIOD_NS=200 → 5 MHz */ +#define ARCHI_FPGA_FREQUENCY 5000000U +/* FC/SOC clock (clk_soc): FC_CLK_PERIOD_NS=100 → 10 MHz */ +#define ARCHI_SOC_FREQUENCY 10000000U +#define ARCHI_NUM_TIMER 1U +#define ARCHI_NUM_FLL 2U + +#define ARCHI_REF_CLOCK_LOG2 15U +#define ARCHI_REF_CLOCK (1U << ARCHI_REF_CLOCK_LOG2) + +#define ARCHI_NB_FLL 3U + +#define __RT_FLL_CL 2U +#define __RT_FLL_PERIPH 1U +#define __RT_FLL_FC 0U + +#define __RT_FREQ_DOMAIN_FC 0U +#define __RT_FREQ_DOMAIN_CL 2U +#define __RT_FREQ_DOMAIN_PERIPH 1U +#define RT_FREQ_NB_DOMAIN 3U + +#define DEFAULT_SYSTEM_CLOCK 50000000U + +#endif /* PROPERTIES_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/pulp_mem_map.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/pulp_mem_map.h new file mode 100644 index 00000000..32757d62 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/pulp_mem_map.h @@ -0,0 +1,103 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef PULP_MEM_MAP_H +#define PULP_MEM_MAP_H + +#ifndef PULP_SOC_PERIPHERALS_ADDR +#define PULP_SOC_PERIPHERALS_ADDR 0x1A100000UL +#endif + +#ifndef PULP_FC_TIMER_SIZE +#define PULP_FC_TIMER_SIZE 0x00000800UL +#endif + +#ifndef PULP_FLL_OFFSET +#define PULP_FLL_OFFSET 0x00000000UL +#endif +#ifndef PULP_GPIO_OFFSET +#define PULP_GPIO_OFFSET 0x00001000UL +#endif +#ifndef PULP_UDMA_OFFSET +#define PULP_UDMA_OFFSET 0x00002000UL +#endif +#ifndef PULP_APB_SOC_CTRL_OFFSET +#define PULP_APB_SOC_CTRL_OFFSET 0x00004000UL +#endif +#ifndef PULP_ADV_TIMER_OFFSET +#define PULP_ADV_TIMER_OFFSET 0x00005000UL +#endif +#ifndef PULP_SOC_EU_OFFSET +#define PULP_SOC_EU_OFFSET 0x00006000UL +#endif +#ifndef PULP_FC_IRQ_OFFSET +#define PULP_FC_IRQ_OFFSET 0x00009800UL +#endif +#ifndef PULP_FC_TIMER_OFFSET +#define PULP_FC_TIMER_OFFSET 0x0000B000UL +#endif +#ifndef PULP_FC_HWPE_OFFSET +#define PULP_FC_HWPE_OFFSET 0x0000C000UL +#endif +#ifndef PULP_STDOUT_OFFSET +#define PULP_STDOUT_OFFSET 0x0000F000UL +#endif +#ifndef PULP_DEBUG_OFFSET +#define PULP_DEBUG_OFFSET 0x00010000UL +#endif + +#ifndef PULP_FLL_ADDR +#define PULP_FLL_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FLL_OFFSET) +#endif +#ifndef PULP_GPIO_ADDR +#define PULP_GPIO_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_GPIO_OFFSET) +#endif +#ifndef PULP_UDMA_ADDR +#define PULP_UDMA_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_UDMA_OFFSET) +#endif +#ifndef PULP_APB_SOC_CTRL_ADDR +#define PULP_APB_SOC_CTRL_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_APB_SOC_CTRL_OFFSET) +#endif +#ifndef PULP_ADV_TIMER_ADDR +#define PULP_ADV_TIMER_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_ADV_TIMER_OFFSET) +#endif +#ifndef PULP_SOC_EU_ADDR +#define PULP_SOC_EU_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_SOC_EU_OFFSET) +#endif +#ifndef PULP_FC_IRQ_ADDR +#define PULP_FC_IRQ_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_IRQ_OFFSET) +#endif +#ifndef PULP_FC_TIMER_ADDR +#define PULP_FC_TIMER_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_TIMER_OFFSET) +#endif +#ifndef PULP_FC_HWPE_ADDR +#define PULP_FC_HWPE_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_FC_HWPE_OFFSET) +#endif +#ifndef PULP_STDOUT_ADDR +#define PULP_STDOUT_ADDR (PULP_SOC_PERIPHERALS_ADDR + PULP_STDOUT_OFFSET) +#endif + +#define PULP_FLL_AREA_SIZE 0x00000010UL + +/* UDMA */ +#define UDMA_CH_ADDR_CTRL (PULP_UDMA_ADDR) +#define UDMA_CH_ADDR_UART (PULP_UDMA_ADDR + 0x80U) +#define UDMA_CH_ADDR_I2CM0 (PULP_UDMA_ADDR + 5U * UDMA_CH_SIZE) +#define UDMA_CH_ADDR_I2CM1 (PULP_UDMA_ADDR + 6U * UDMA_CH_SIZE) +#define UDMA_CTRL_I2CM0_CLKEN BIT(4) +#define UDMA_CTRL_I2CM1_CLKEN BIT(5) +#define UDMA_CH_SIZE (0x80U) +#define N_UART (2U) + +#endif /* PULP_MEM_MAP_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/string.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/string.h new file mode 100644 index 00000000..b5600000 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/string.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 STRING_H +#define STRING_H + +#include <stddef.h> + +void *memcpy(void *dest, const void *src, size_t n); +void *memset(void *dest, int c, size_t n); +int memcmp(const void *lhs, const void *rhs, size_t n); + +#endif /* STRING_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/system_core_v_mcu.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/system_core_v_mcu.h new file mode 100644 index 00000000..4b445e31 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/system_core_v_mcu.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 SYSTEM_CORE_V_MCU_H +#define SYSTEM_CORE_V_MCU_H + +#include <stdint.h> + +extern void (*isr_table[32])(void); +extern volatile uint32_t system_core_clock; + +void system_init(void); +void tx_trap_handler(uint32_t mcause, uint32_t mepc, uint32_t mtval); +void tx_timer_irq_handler(void); +void tx_undefined_irq_handler(void); + +#endif /* SYSTEM_CORE_V_MCU_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/temp_sensor.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/temp_sensor.h new file mode 100644 index 00000000..e94c589a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/temp_sensor.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 TEMP_SENSOR_H +#define TEMP_SENSOR_H + +#include <stdint.h> + +/* Read ADT7420 temperature sensor on I2CM1 (Nexys A7 on-board sensor). + * Returns temperature in tenths of degrees Celsius (e.g. 213 = 21.3°C). + * Returns INT16_MIN on I2C error. */ +int16_t temp_read_celsius_x10(void); + +/* Initialize the temperature sensor I2C channel. Call once at startup. */ +void temp_sensor_init(void); + +#endif /* TEMP_SENSOR_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer.h new file mode 100644 index 00000000..ecfc0480 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer.h @@ -0,0 +1,120 @@ +/***************************************************************************/ +/* Copyright (C) 2019 ETH Zurich and University of Bologna + * Copyright (C) 2026 Eclipse ThreadX contributors + * + * Derived from core-v-freertos (https://github.com/openhwgroup/core-v-freertos) + * Original work licensed under the Apache License, Version 2.0. + * See https://www.apache.org/licenses/LICENSE-2.0 + * Modifications licensed under MIT (https://opensource.org/licenses/MIT). + * + * AI Disclosure: Some portions generated or modified by Copilot (Sonnet 4.6). + * + * SPDX-License-Identifier: Apache-2.0 AND MIT + ***************************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +#include "bits.h" + +#define TIMER_CFG_LO_OFFSET 0x0U +#define TIMER_CFG_HI_OFFSET 0x4U +#define TIMER_CNT_LO_OFFSET 0x8U +#define TIMER_CNT_HI_OFFSET 0xCU +#define TIMER_CMP_LO_OFFSET 0x10U +#define TIMER_CMP_HI_OFFSET 0x14U +#define TIMER_START_LO_OFFSET 0x18U +#define TIMER_START_HI_OFFSET 0x1CU +#define TIMER_RESET_LO_OFFSET 0x20U +#define TIMER_RESET_HI_OFFSET 0x24U + +#define TIMER_CFG_LO_ENABLE_BIT 0U +#define TIMER_CFG_LO_ENABLE_WIDTH 1U +#define TIMER_CFG_LO_ENABLE_MASK 0x1U +#define TIMER_CFG_LO_RESET_BIT 1U +#define TIMER_CFG_LO_RESET_WIDTH 1U +#define TIMER_CFG_LO_RESET_MASK 0x2U +#define TIMER_CFG_LO_IRQEN_BIT 2U +#define TIMER_CFG_LO_IRQEN_WIDTH 1U +#define TIMER_CFG_LO_IRQEN_MASK 0x4U +#define TIMER_CFG_LO_IEM_BIT 3U +#define TIMER_CFG_LO_IEM_WIDTH 1U +#define TIMER_CFG_LO_IEM_MASK 0x8U +#define TIMER_CFG_LO_MODE_BIT 4U +#define TIMER_CFG_LO_MODE_WIDTH 1U +#define TIMER_CFG_LO_MODE_MASK 0x10U +#define TIMER_CFG_LO_ONE_S_BIT 5U +#define TIMER_CFG_LO_ONE_S_WIDTH 1U +#define TIMER_CFG_LO_ONE_S_MASK 0x20U +#define TIMER_CFG_LO_PEN_BIT 6U +#define TIMER_CFG_LO_PEN_WIDTH 1U +#define TIMER_CFG_LO_PEN_MASK 0x40U +#define TIMER_CFG_LO_CCFG_BIT 7U +#define TIMER_CFG_LO_CCFG_WIDTH 1U +#define TIMER_CFG_LO_CCFG_MASK 0x80U +#define TIMER_CFG_LO_PVAL_BIT 8U +#define TIMER_CFG_LO_PVAL_WIDTH 8U +#define TIMER_CFG_LO_PVAL_MASK 0xFF00U +#define TIMER_CFG_LO_CASC_BIT 31U +#define TIMER_CFG_LO_CASC_WIDTH 1U +#define TIMER_CFG_LO_CASC_MASK 0x80000000UL + +#define TIMER_CFG_HI_ENABLE_BIT 0U +#define TIMER_CFG_HI_ENABLE_WIDTH 1U +#define TIMER_CFG_HI_ENABLE_MASK 0x1U +#define TIMER_CFG_HI_RESET_BIT 1U +#define TIMER_CFG_HI_RESET_WIDTH 1U +#define TIMER_CFG_HI_RESET_MASK 0x2U +#define TIMER_CFG_HI_IRQEN_BIT 2U +#define TIMER_CFG_HI_IRQEN_WIDTH 1U +#define TIMER_CFG_HI_IRQEN_MASK 0x4U +#define TIMER_CFG_HI_IEM_BIT 3U +#define TIMER_CFG_HI_IEM_WIDTH 1U +#define TIMER_CFG_HI_IEM_MASK 0x8U +#define TIMER_CFG_HI_MODE_BIT 4U +#define TIMER_CFG_HI_MODE_WIDTH 1U +#define TIMER_CFG_HI_MODE_MASK 0x10U +#define TIMER_CFG_HI_ONE_S_BIT 5U +#define TIMER_CFG_HI_ONE_S_WIDTH 1U +#define TIMER_CFG_HI_ONE_S_MASK 0x20U +#define TIMER_CFG_HI_PEN_BIT 6U +#define TIMER_CFG_HI_PEN_WIDTH 1U +#define TIMER_CFG_HI_PEN_MASK 0x40U +#define TIMER_CFG_HI_CLKCFG_BIT 7U +#define TIMER_CFG_HI_CLKCFG_WIDTH 1U +#define TIMER_CFG_HI_CLKCFG_MASK 0x80U + +#define TIMER_CNT_LO_CNT_LO_BIT 0U +#define TIMER_CNT_LO_CNT_LO_WIDTH 32U +#define TIMER_CNT_LO_CNT_LO_MASK 0xFFFFFFFFUL +#define TIMER_CNT_HI_CNT_HI_BIT 0U +#define TIMER_CNT_HI_CNT_HI_WIDTH 32U +#define TIMER_CNT_HI_CNT_HI_MASK 0xFFFFFFFFUL +#define TIMER_CMP_LO_CMP_LO_BIT 0U +#define TIMER_CMP_LO_CMP_LO_WIDTH 32U +#define TIMER_CMP_LO_CMP_LO_MASK 0xFFFFFFFFUL +#define TIMER_CMP_HI_CMP_HI_BIT 0U +#define TIMER_CMP_HI_CMP_HI_WIDTH 32U +#define TIMER_CMP_HI_CMP_HI_MASK 0xFFFFFFFFUL + +#define TIMER_START_LO_STRT_LO_BIT 0U +#define TIMER_START_LO_STRT_LO_WIDTH 1U +#define TIMER_START_LO_STRT_LO_MASK 0x1U +#define TIMER_START_HI_STRT_HI_BIT 0U +#define TIMER_START_HI_STRT_HI_WIDTH 1U +#define TIMER_START_HI_STRT_HI_MASK 0x1U +#define TIMER_RESET_LO_RST_LO_BIT 0U +#define TIMER_RESET_LO_RST_LO_WIDTH 1U +#define TIMER_RESET_LO_RST_LO_MASK 0x1U +#define TIMER_RESET_HI_RST_HI_BIT 0U +#define TIMER_RESET_HI_RST_HI_WIDTH 1U +#define TIMER_RESET_HI_RST_HI_MASK 0x1U + +struct pulp_timer +{ + unsigned int current_time; + unsigned int flags; + void *base; +}; + +#endif /* TIMER_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer_irq.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer_irq.h new file mode 100644 index 00000000..11e0d76a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/timer_irq.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 TIMER_IRQ_H +#define TIMER_IRQ_H + +#include <stdint.h> + +int timer_irq_init(uint32_t ticks); +int timer_irq_set_timeout(uint32_t ticks); +uint32_t timer_irq_clock_elapsed(void); +uint32_t timer_irq_cycle_get_32(void); + +#endif /* TIMER_IRQ_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/tx_user.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/tx_user.h new file mode 100644 index 00000000..cc104032 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/tx_user.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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_USER_H +#define TX_USER_H + +#define TX_TIMER_TICKS_PER_SECOND 100U +#define TX_INCLUDE_USER_DEFINE_FILE + +#endif /* TX_USER_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/include/uart_driver.h b/ports/risc-v32/gnu/example_build/core_v_mcu/include/uart_driver.h new file mode 100644 index 00000000..c1771093 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/include/uart_driver.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 UART_DRIVER_H +#define UART_DRIVER_H + +#include <stdint.h> + +int uart_init(uint8_t uart_id, uint32_t baudrate, uint32_t periph_freq); +void uart_write_byte(uint8_t uart_id, uint8_t c); +int uart_read_byte(uint8_t uart_id); +void uart_write_str(uint8_t uart_id, const char *str); +void uart_write_buf(uint8_t uart_id, const uint8_t *buf, uint32_t len); + +#endif /* UART_DRIVER_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh b/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh new file mode 100755 index 00000000..d0192665 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env 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. +# * +# * SPDX-License-Identifier: MIT +# ***************************************************************************/ + +# install_deps.sh -- Install Linux build/debug dependencies for the CORE-V MCU ThreadX port. +# +# Supported: Ubuntu 20.04 / 22.04 / 24.04 and Debian derivatives. +# Run as a regular user; sudo is invoked internally where needed. +# +# Installs: +# - xPack riscv-none-elf-gcc (multilib bare-metal toolchain, rv32imc/ilp32 capable) +# - cmake, ninja-build, gdb-multiarch, openocd, usbutils +# +# Usage: +# bash install_deps.sh + +set -euo pipefail + +die() { echo "[ERROR] $*" >&2; exit 1; } +info() { echo "[INFO] $*"; } + +command -v apt-get >/dev/null 2>&1 || die "This script requires apt-get (Ubuntu/Debian)." + +# --------------------------------------------------------------------------- +# xPack riscv-none-elf-gcc +# Cross-platform multilib toolchain (Linux/macOS/Windows). +# Includes rv32imc/ilp32 (soft-float) libgcc — required for CV32E40P. +# See: https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +# --------------------------------------------------------------------------- +XPACK_VERSION="15.2.0-1" +XPACK_TARBALL="xpack-riscv-none-elf-gcc-${XPACK_VERSION}-linux-x64.tar.gz" +XPACK_URL="https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v${XPACK_VERSION}/${XPACK_TARBALL}" +XPACK_INSTALL_DIR="/opt/xpack-riscv-none-elf-gcc-${XPACK_VERSION}" +XPACK_BIN="${XPACK_INSTALL_DIR}/bin" + +APT_PACKAGES=( + cmake + ninja-build + gdb-multiarch + openocd + usbutils + git +) + +info "Updating package lists ..." +sudo apt-get update -qq + +info "Installing apt packages: ${APT_PACKAGES[*]}" +sudo apt-get install -y "${APT_PACKAGES[@]}" + +if [ -x "${XPACK_BIN}/riscv-none-elf-gcc" ]; then + info "xPack riscv-none-elf-gcc ${XPACK_VERSION} already installed at ${XPACK_INSTALL_DIR}" +else + info "Downloading xPack riscv-none-elf-gcc ${XPACK_VERSION} ..." + wget --no-verbose "${XPACK_URL}" -O "/tmp/${XPACK_TARBALL}" + sudo mkdir -p "${XPACK_INSTALL_DIR}" + sudo tar xzf "/tmp/${XPACK_TARBALL}" -C /opt + rm "/tmp/${XPACK_TARBALL}" + info "Installed to ${XPACK_INSTALL_DIR}" +fi + +info "" +info "Add the toolchain to your PATH:" +info " export PATH=${XPACK_BIN}:\$PATH" +info "" +info "All dependencies installed." +info "" +info "Next steps:" +info " 1. Run scripts/setup_opella.sh to configure udev rules for the Ashling Opella LD." +info " 2. (WSL only) Follow the usbipd-win instructions printed by setup_opella.sh." + diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/link.ld b/ports/risc-v32/gnu/example_build/core_v_mcu/link.ld new file mode 100644 index 00000000..8ffb174e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/link.ld @@ -0,0 +1,65 @@ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +MEMORY +{ + L2 (rwx) : ORIGIN = 0x1c000000, LENGTH = 0x80000 +} + +SECTIONS +{ + PROVIDE(__boot_address = 0x1c000880); + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x2000; + PROVIDE(__stack_size = __stack_size); + + .vectors 0x1c000800 : + { + __vector_start = .; + KEEP(*(.vectors)) + . = __vector_start + 0x80; + __vector_end = .; + } > L2 + + .text __boot_address : + { + *(.text.start) + *(.text .text.*) + *(.rodata .rodata.*) + . = ALIGN(4); + } > L2 + + .data : + { + __data_begin = .; + __sdata_begin = .; + *(.sdata .sdata.*) + *(.data .data.*) + . = ALIGN(4); + __data_end = .; + } > L2 + + .bss (NOLOAD) : + { + __bss_start = .; + *(.sbss .sbss.*) + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + _end = .; + } > L2 + + PROVIDE(__tx_free_memory_start = __bss_end); + PROVIDE(__global_pointer$ = MIN(__sdata_begin + 0x800, + MAX(__data_begin + 0x800, __bss_end - 0x800))); + + __stack_top = ORIGIN(L2) + LENGTH(L2); + + ASSERT(SIZEOF(.vectors) <= 128, "Vector table exceeds reserved 128 bytes") + + /DISCARD/ : + { + *(.eh_frame) + *(.note.*) + } +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg b/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg new file mode 100644 index 00000000..db43eae5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/openocd-nexys-Ashling-Opella-LD.cfg @@ -0,0 +1,41 @@ +interface ftdi +ftdi_device_desc "Opella-LD Debug Probe" +ftdi_vid_pid 0x0B6B 0x0040 +ftdi_tdo_sample_edge falling +ftdi_layout_init 0x0A68 0xFF7B +ftdi_channel 0 +ftdi_layout_signal JTAGOE -ndata 0x0010 +ftdi_layout_signal nTRST -data 0x0020 +ftdi_layout_signal nSRST -data 0x0040 +ftdi_layout_signal SWD_EN -data 0x0100 +ftdi_layout_signal SWDIO_OE -data 0x0200 +ftdi_layout_signal LED -ndata 0x0800 +transport select jtag + + +reset_config none + +adapter_khz 1000 + +set _CHIPNAME riscv + +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10001C05 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME + +gdb_report_data_abort enable +gdb_report_register_access_error enable + +riscv set_reset_timeout_sec 120 +riscv set_command_timeout_sec 120 + +# prefer to use sba for system bus access +riscv set_prefer_sba on + +# dump jtag chain +scan_chain + +init +halt +echo "Ready for Remote Connections"
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tests/CMakeLists.txt b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/CMakeLists.txt new file mode 100644 index 00000000..6726981f --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) +project(core_v_mcu_tests C) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(CORE_V_MCU_DIR ${CMAKE_CURRENT_LIST_DIR}/..) + +add_executable(test_irq + ${CMAKE_CURRENT_LIST_DIR}/test_irq.c + ${CMAKE_CURRENT_LIST_DIR}/mock/mmio_mock.c +) +target_include_directories(test_irq PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/mock + ${CORE_V_MCU_DIR}/include +) + +add_executable(test_timer + ${CMAKE_CURRENT_LIST_DIR}/test_timer.c + ${CMAKE_CURRENT_LIST_DIR}/mock/mmio_mock.c +) +target_include_directories(test_timer PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/mock + ${CORE_V_MCU_DIR}/include +) + +enable_testing() +add_test(NAME irq_tests COMMAND test_irq) +add_test(NAME timer_tests COMMAND test_timer) diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.c b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.c new file mode 100644 index 00000000..7852d5f1 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.c @@ -0,0 +1,18 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 "mmio_mock.h" + +uint32_t mock_mmio[MOCK_MMIO_SIZE]; diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.h b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.h new file mode 100644 index 00000000..c8839e1e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/mock/mmio_mock.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 MMIO_MOCK_H +#define MMIO_MOCK_H + +#include <stdint.h> +#include <string.h> + +#define CORE_V_MCU_MMIO_MOCK 1 +#define MOCK_MMIO_SIZE 1024U + +extern uint32_t mock_mmio[MOCK_MMIO_SIZE]; + +static inline void writew(uint32_t val, uintptr_t addr) +{ + if (addr < (uintptr_t)(MOCK_MMIO_SIZE * 4U)) + { + mock_mmio[addr / 4U] = val; + } +} + +static inline uint32_t readw(const uintptr_t addr) +{ + if (addr < (uintptr_t)(MOCK_MMIO_SIZE * 4U)) + { + return mock_mmio[addr / 4U]; + } + + return 0U; +} + +#endif /* MMIO_MOCK_H */ diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_irq.c b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_irq.c new file mode 100644 index 00000000..72c17f49 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_irq.c @@ -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 Copilot (Sonnet 4.6). + * 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 <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include "mmio_mock.h" + +static uint32_t mock_mstatus = 0U; +#define csr_read(csr) (mock_mstatus) +#define csr_write(csr, val) do { mock_mstatus = (uint32_t)(val); } while (0) +#define csr_read_clear(csr, val) ({ uint32_t _v = mock_mstatus; mock_mstatus &= ~(uint32_t)(val); _v; }) +#define csr_read_set(csr, val) ({ uint32_t _v = mock_mstatus; mock_mstatus |= (uint32_t)(val); _v; }) + +#include "bits.h" +#define PULP_SOC_PERIPHERALS_ADDR 0U +#define PULP_FC_IRQ_OFFSET 0U +#include "irq.h" +#include "../../bsp/irq.c" + +static void test_irq_enable(void) +{ + memset(mock_mmio, 0, sizeof(mock_mmio)); + irq_enable(BIT(10)); + assert(mock_mmio[IRQ_REG_MASK_SET_OFFSET / 4U] == BIT(10)); + printf("test_irq_enable: PASS\n"); +} + +static void test_irq_disable(void) +{ + memset(mock_mmio, 0, sizeof(mock_mmio)); + irq_disable(BIT(10)); + assert(mock_mmio[IRQ_REG_MASK_CLEAR_OFFSET / 4U] == BIT(10)); + printf("test_irq_disable: PASS\n"); +} + +static void test_irq_clint_enable(void) +{ + mock_mstatus = 0U; + (void)irq_clint_enable(); + assert((mock_mstatus & 0x8U) != 0U); + printf("test_irq_clint_enable: PASS\n"); +} + +int main(void) +{ + test_irq_enable(); + test_irq_disable(); + test_irq_clint_enable(); + printf("All IRQ tests passed.\n"); + return 0; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_timer.c b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_timer.c new file mode 100644 index 00000000..3e1499e7 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tests/test_timer.c @@ -0,0 +1,53 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include "mmio_mock.h" +#define PULP_SOC_PERIPHERALS_ADDR 0U +#define PULP_FC_TIMER_OFFSET 0U + +#include "bits.h" +#include "timer.h" +#include "timer_irq.h" +#include "../../bsp/timer_irq.c" + +static void test_timer_irq_init(void) +{ + uint32_t cfg; + int ret; + + memset(mock_mmio, 0, sizeof(mock_mmio)); + ret = timer_irq_init(327U); + assert(ret == 0); + assert(mock_mmio[TIMER_CMP_LO_OFFSET / 4U] == 327U); + + cfg = mock_mmio[TIMER_CFG_LO_OFFSET / 4U]; + assert((cfg & TIMER_CFG_LO_ENABLE_MASK) != 0U); + assert((cfg & TIMER_CFG_LO_IRQEN_MASK) != 0U); + assert((cfg & TIMER_CFG_LO_CCFG_MASK) != 0U); + assert((cfg & TIMER_CFG_LO_MODE_MASK) != 0U); + printf("test_timer_irq_init: PASS\n"); +} + +int main(void) +{ + test_timer_irq_init(); + printf("All timer tests passed.\n"); + return 0; +} diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/tx_initialize_low_level.S b/ports/risc-v32/gnu/example_build/core_v_mcu/tx_initialize_low_level.S new file mode 100644 index 00000000..3c5a3888 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/tx_initialize_low_level.S @@ -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 Copilot (Sonnet 4.6). + * 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 + **************************************************************************/ + + .section .data + .global __tx_free_memory_start +__tx_free_memory_start: + + .section .text.trap_entry + .align 4 + .global tx_trap_entry + .extern _tx_thread_context_save + .extern _tx_thread_context_restore + .extern tx_trap_handler + +tx_trap_entry: + addi sp, sp, -128 + sw ra, 112(sp) + call _tx_thread_context_save + csrr a0, mcause + csrr a1, mepc + csrr a2, mtval + addi sp, sp, -4 + sw ra, 0(sp) + call tx_trap_handler + lw ra, 0(sp) + addi sp, sp, 4 + call _tx_thread_context_restore +1: + wfi + j 1b + + .section .text + .global _tx_initialize_low_level + .weak _tx_initialize_low_level + .extern _tx_thread_system_stack_ptr + .extern _tx_initialize_unused_memory + .extern __vector_start + +_tx_initialize_low_level: + la t0, _tx_thread_system_stack_ptr + sw sp, 0(t0) + + la t0, __tx_free_memory_start + la t1, _tx_initialize_unused_memory + sw t0, 0(t1) + + la t0, __vector_start + ori t0, t0, 1 + csrw mtvec, t0 + + ret diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/vectors.S b/ports/risc-v32/gnu/example_build/core_v_mcu/vectors.S new file mode 100644 index 00000000..f6a57d7a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/vectors.S @@ -0,0 +1,25 @@ +/*************************************************************************** + * 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 (Sonnet 4.6). + * 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 + **************************************************************************/ + + .section .vectors, "ax" + .option norvc + .align 2 + .extern tx_trap_entry + .global __vector_start + +__vector_start: + .rept 32 + jal zero, tx_trap_entry + .endr diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/board.c b/ports/risc-v32/gnu/example_build/cva6_ariane/board.c new file mode 100644 index 00000000..b1c7e5c5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/board.c @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (c) 2026 Quintauris + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "plic.h" +#include "hwtimer.h" +#include "uart.h" +#include <stdint.h> +#include <stddef.h> + +void *memset(const 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<n;i++) + t[i]=c; + return t; +} + + +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-v32/gnu/example_build/cva6_ariane/build_libthreadx.sh b/ports/risc-v32/gnu/example_build/cva6_ariane/build_libthreadx.sh new file mode 100644 index 00000000..23f707dc --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/build_libthreadx.sh @@ -0,0 +1,17 @@ +#!/bin/bash +############################################################################## +# 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 +############################################################################## + + +pushd ../../../../../ +cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_gnu.cmake -DSOFT_FLOAT=1 . +cmake --build ./build/ +popd diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/csr.h b/ports/risc-v32/gnu/example_build/cva6_ariane/csr.h new file mode 100644 index 00000000..1bffcf39 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/csr.h @@ -0,0 +1,360 @@ +/*************************************************************************** + * Copyright (c) 2026 Quintauris + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + + +#ifndef RISCV_CSR_H +#define RISCV_CSR_H + + +// Machine Status Register, mstatus +#define MSTATUS_MPP_MASK (3L << 11) // previous mode. +#define MSTATUS_MPP_M (3L << 11) +#define MSTATUS_MPP_S (1L << 11) +#define MSTATUS_MPP_U (0L << 11) +#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. +#define MSTATUS_MPIE (1L << 7) +#define MSTATUS_FS (1L << 13) + +// Machine-mode Interrupt Enable +#define MIE_MTIE (1L << 7) +#define MIE_MSIE (1L << 3) +#define MIE_MEIE (1L << 11) +#define MIE_STIE (1L << 5) // supervisor timer +#define MIE_SSIE (1L << 1) +#define MIE_SEIE (1L << 9) + +// Supervisor Status Register, sstatus +#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User +#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable +#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable +#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable +#define SSTATUS_UIE (1L << 0) // User Interrupt Enable +#define SSTATUS_SPIE (1L << 5) +#define SSTATUS_UPIE (1L << 4) + +// Supervisor Interrupt Enable +#define SIE_SEIE (1L << 9) // external +#define SIE_STIE (1L << 5) // timer +#define SIE_SSIE (1L << 1) // software + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +static inline uint32_t riscv_get_core() +{ + uint32_t x; + asm volatile("csrr %0, mhartid" : "=r" (x) ); + return x; +} + +static inline uint64_t riscv_get_mstatus() +{ + uint32_t x; + uint32_t xh; + asm volatile("csrr %0, mstatus" : "=r" (x) ); + asm volatile("csrr %0, mstatush" : "=r" (xh) ); + return ((uint64_t)(x)) + ((uint64_t)(xh)) << 32; +} + +static inline void riscv_writ_mstatus(uint64_t x) +{ + asm volatile("csrw mstatus, %0" : : "r" ((uint32_t)x)); + asm volatile("csrw mstatush, %0" : : "r" ((uint32_t)(x >> 32))); +} + +// machine exception program counter, holds the +// instruction address to which a return from +// exception will go. +static inline void riscv_writ_mepc(uint32_t x) +{ + asm volatile("csrw mepc, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_sstatus() +{ + uint32_t x; + asm volatile("csrr %0, sstatus" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_sstatus(uint32_t x) +{ + asm volatile("csrw sstatus, %0" : : "r" (x)); +} + +// Supervisor Interrupt Pending +static inline uint32_t riscv_get_sip() +{ + uint32_t x; + asm volatile("csrr %0, sip" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_sip(uint32_t x) +{ + asm volatile("csrw sip, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_sie() +{ + uint32_t x; + asm volatile("csrr %0, sie" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_sie(uint32_t x) +{ + asm volatile("csrw sie, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_mie() +{ + uint32_t x; + asm volatile("csrr %0, mie" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_mie(uint32_t x) +{ + asm volatile("csrw mie, %0" : : "r" (x)); +} + +// supervisor exception program counter, holds the +// instruction address to which a return from +// exception will go. +static inline void riscv_writ_sepc(uint32_t x) +{ + asm volatile("csrw sepc, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_sepc() +{ + uint32_t x; + asm volatile("csrr %0, sepc" : "=r" (x) ); + return x; +} + +// Machine Exception Delegation +static inline uint32_t riscv_get_medeleg() +{ + uint32_t x; + asm volatile("csrr %0, medeleg" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_medeleg(uint32_t x) +{ + asm volatile("csrw medeleg, %0" : : "r" (x)); +} + +// Machine Interrupt Delegation +static inline uint32_t riscv_get_mideleg() +{ + uint32_t x; + asm volatile("csrr %0, mideleg" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_mideleg(uint32_t x) +{ + asm volatile("csrw mideleg, %0" : : "r" (x)); +} + +// Supervisor Trap-Vector Base Address +// low two bits are mode. +static inline void riscv_writ_stvec(uint32_t x) +{ + asm volatile("csrw stvec, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_stvec() +{ + uint32_t x; + asm volatile("csrr %0, stvec" : "=r" (x) ); + return x; +} + +static inline uint32_t riscv_get_stimecmp() +{ + uint32_t x; + asm volatile("csrr %0, 0x14d" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_stimecmp(uint32_t x) +{ + asm volatile("csrw 0x14d, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_menvcfg() +{ + uint32_t x; + asm volatile("csrr %0, 0x30a" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_menvcfg(uint32_t x) +{ + asm volatile("csrw 0x30a, %0" : : "r" (x)); +} + +static inline void riscv_writ_pmpcfg0(uint32_t x) +{ + asm volatile("csrw pmpcfg0, %0" : : "r" (x)); +} + +static inline void riscv_writ_pmpaddr0(uint32_t x) +{ + asm volatile("csrw pmpaddr0, %0" : : "r" (x)); +} + +static inline void riscv_writ_satp(uint32_t x) +{ + asm volatile("csrw satp, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_satp() +{ + uint32_t x; + asm volatile("csrr %0, satp" : "=r" (x) ); + return x; +} + +static inline uint32_t riscv_get_scause() +{ + uint32_t x; + asm volatile("csrr %0, scause" : "=r" (x) ); + return x; +} + +static inline uint32_t riscv_get_stval() +{ + uint32_t x; + asm volatile("csrr %0, stval" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_mcounteren(uint32_t x) +{ + asm volatile("csrw mcounteren, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_mcounteren() +{ + uint32_t x; + asm volatile("csrr %0, mcounteren" : "=r" (x) ); + return x; +} + +// machine-mode cycle counter +static inline uint64_t riscv_get_time() +{ + uint32_t x; + uint32_t xh; + asm volatile("csrr %0, time" : "=r" (x) ); + asm volatile("csrr %0, timeh" : "=r" (xh) ); + return ((uint64_t)(x)) + ((uint64_t)(xh)) << 32; +} + +static inline void riscv_sintr_on() +{ + uint32_t sstatus = riscv_get_sstatus(); + sstatus |= SSTATUS_SIE; + riscv_writ_sstatus(sstatus); +} + +static inline void riscv_sintr_off() +{ + uint32_t sstatus = riscv_get_sstatus(); + sstatus &= (~SSTATUS_SIE); + riscv_writ_sstatus(sstatus); +} + +static inline int riscv_sintr_get() +{ + uint32_t x = riscv_get_sstatus(); + return (x & SSTATUS_SIE) != 0; +} + +static inline void riscv_sintr_restore(int x) +{ + if(x) + riscv_sintr_on(); + else + riscv_sintr_off(); +} + +static inline void riscv_mintr_on() +{ + uint32_t mstatus = riscv_get_mstatus(); + mstatus |= MSTATUS_MIE; + riscv_writ_mstatus(mstatus); +} + +static inline void riscv_mintr_off() +{ + uint32_t mstatus = riscv_get_mstatus(); + mstatus &= (~MSTATUS_MIE); + riscv_writ_mstatus(mstatus); +} + +static inline int riscv_mintr_get() +{ + uint32_t x = riscv_get_mstatus(); + return (x & MSTATUS_MIE) != 0; +} + +static inline void riscv_mintr_restore(int x) +{ + if(x) + riscv_mintr_on(); + else + riscv_mintr_off(); +} + +static inline uint32_t riscv_get_sp() +{ + uint32_t x; + asm volatile("mv %0, sp" : "=r" (x) ); + return x; +} + +// read and write tp, the thread pointer, which xv6 uses to hold +// this core's hartid (core number), the index into cpus[]. +static inline uint32_t riscv_get_tp() +{ + uint32_t x; + asm volatile("mv %0, tp" : "=r" (x) ); + return x; +} + +static inline void riscv_writ_tp(uint32_t x) +{ + asm volatile("mv tp, %0" : : "r" (x)); +} + +static inline uint32_t riscv_get_ra() +{ + uint32_t x; + asm volatile("mv %0, ra" : "=r" (x) ); + return x; +} + +// flush the TLB. +static inline void sfence_vma() +{ + // the zero, zero means flush all TLB entries. + asm volatile("sfence.vma zero, zero"); +} + +#endif // __ASSEMBLER__ + +#endif diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/demo_threadx.c b/ports/risc-v32/gnu/example_build/cva6_ariane/demo_threadx.c new file mode 100644 index 00000000..adc56f4a --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/demo_threadx.c @@ -0,0 +1,404 @@ +/***************************************************************************/ +/* 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 9120 +#define DEMO_BLOCK_POOL_SIZE 100 +#define DEMO_QUEUE_SIZE 100 + +char *_to_str(ULONG val) +{ + static char buf[11]; /* 10 digits max + '\0' */ + char *p = buf + sizeof(buf) - 1; + + *p = '\0'; + do { + *--p = '0' + (val % 10); + val /= 10; + } while (val); + + return p; +} + +/* 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; + + +/* 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", first_unused_memory, 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) { + puts("[Thread 1] ERROR: Failed to send message!"); + 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)){ + puts("[Thread 2] ERROR: Failed to receive message ! Expected # "); + uart_puts(_to_str(thread_2_messages_received)); + puts(", but got # "); + uart_puts(_to_str(received_message)); + 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-v32/gnu/example_build/cva6_ariane/entry.S b/ports/risc-v32/gnu/example_build/cva6_ariane/entry.S new file mode 100644 index 00000000..f9645bc7 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/entry.S @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + + +.section .text +.align 4 +.global _start +.extern main +.extern _sysstack_start +.extern _bss_start +.extern _bss_end +_start: + csrr t0, mhartid + bne t0, zero, 1f + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + la t0, _sysstack_start + li t1, 0x1000 + add sp, t0, t1 + la t0, _bss_start + la t1, _bss_end +_bss_clean_start: + bgeu t0, t1, _bss_clean_end + sb zero, 0(t0) + addi t0, t0, 1 + j _bss_clean_start +_bss_clean_end: + call main +1: + /* todo smp */ + wfi + j 1b diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.c b/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.c new file mode 100644 index 00000000..b5335cf3 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.c @@ -0,0 +1,35 @@ +/*************************************************************************** + * Copyright (c) 2026 Quintauris + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "tx_port.h" +#include "csr.h" +#include "hwtimer.h" + +#define CLINT (0x02000000L) +#define CLINT_TIME (CLINT+0xBFF8) +#define CLINT_TIMECMP(hart_id) (CLINT+0x4000+8*(hart_id)) + + +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 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; +} + diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.h b/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.h new file mode 100644 index 00000000..9e4a066d --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/hwtimer.h @@ -0,0 +1,24 @@ + +/*************************************************************************** + * Copyright (c) 2026 Quintauris + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef RISCV_HWTIMER_H +#define RISCV_HWTIMER_H + +#include <stdint.h> + +#define TICKNUM_PER_SECOND 50000000 +#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 100) + +int hwtimer_init(void); + +int hwtimer_handler(void); + +#endif diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/link.lds b/ports/risc-v32/gnu/example_build/cva6_ariane/link.lds new file mode 100644 index 00000000..619080e7 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/link.lds @@ -0,0 +1,49 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY( _start ) + +SECTIONS +{ + /* + * ensure that entry.S / _entry is at 0x80000000, + * where arianes's -kernel jumps. + */ + . = 0x80000000; + + .text : { + *(.text .text.*) + . = ALIGN(0x1000); + PROVIDE(etext = .); + } + + .rodata : { + . = ALIGN(16); + *(.srodata .srodata.*) /* do not need to distinguish this from .rodata */ + . = ALIGN(16); + *(.rodata .rodata.*) + } + + .data : { + . = ALIGN(16); + *(.sdata .sdata.*) /* do not need to distinguish this from .data */ + . = ALIGN(16); + *(.data .data.*) + } + + .bss : { + . = ALIGN(16); + _bss_start = .; + *(.sbss .sbss.*) /* do not need to distinguish this from .bss */ + . = ALIGN(16); + *(.bss .bss.*) + _bss_end = .; + } + + .stack : { + . = ALIGN(4096); + _sysstack_start = .; + . += 0x1000; + _sysstack_end = .; + } + + PROVIDE(_end = .); +} diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/plic.c b/ports/risc-v32/gnu/example_build/cva6_ariane/plic.c new file mode 120000 index 00000000..b247f4fe --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/plic.c @@ -0,0 +1 @@ +../../../../risc-v_common/example_build/plic/plic.c
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/plic.h b/ports/risc-v32/gnu/example_build/cva6_ariane/plic.h new file mode 120000 index 00000000..f776a3d2 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/plic.h @@ -0,0 +1 @@ +../../../../risc-v_common/example_build/plic/plic.h
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/trap.c b/ports/risc-v32/gnu/example_build/cva6_ariane/trap.c new file mode 100644 index 00000000..520b74a5 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/trap.c @@ -0,0 +1,77 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + +#include "csr.h" +#include <stdint.h> +#include "uart.h" +#include "hwtimer.h" +#include "plic.h" +#include <tx_port.h> +#include <tx_api.h> + +#define OS_IS_INTERUPT(mcause) (mcause & 0x80000000u) +#define OS_IS_EXCEPTION(mcause) (~(OS_IS_INTERUPT)) +#define OS_IS_TICK_INT(mcause) (mcause == 0x80000007u) +#define OS_IS_SOFT_INT(mcause) (mcause == 0x80000003u) +#define OS_IS_EXT_INT(mcause) (mcause == 0x8000000bu) +#define OS_IS_TRAP_USER(mcause) (mcause == 0x0000000bu) +extern void _tx_timer_interrupt(void); + +extern int uart_putc(int ch); + +static void print_hex(uintptr_t val) +{ + char digits[] = "0123456789ABCDEF"; + uart_putc('0'); + uart_putc('x'); + for(int i = (sizeof(uintptr_t)*2) - 1; i >= 0; i--) { + int d = (val >> (i*4)) & 0xF; + uart_putc(digits[d]); + } + uart_putc('\n'); +} + +void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) +{ + if(OS_IS_INTERUPT(mcause)) + { + if(OS_IS_TICK_INT(mcause)) + { + hwtimer_handler(); + _tx_timer_interrupt(); + } + else if(OS_IS_EXT_INT(mcause)) + { + int ret = plic_irq_intr(); + if(ret) + { + puts("[INTERRUPT]: handler irq error!"); + while(1) ; + } + } + else + { + puts("[INTERRUPT]: now can't deal with the interrupt!"); + while(1) ; + } + } + else + { + puts("[EXCEPTION] : Unkown Error!!"); + puts("mcause:"); + print_hex(mcause); + puts("mepc:"); + print_hex(mepc); + puts("mtval:"); + print_hex(mtval); + while(1) ; + } +} diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/tx_initialize_low_level.S b/ports/risc-v32/gnu/example_build/cva6_ariane/tx_initialize_low_level.S new file mode 100644 index 00000000..16910f76 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/tx_initialize_low_level.S @@ -0,0 +1,163 @@ +/*************************************************************************** + * Copyright (c) 2026 Quintauris + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "csr.h" +#include "tx_port.h" + + .section .text + .align 4 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* trap_entry RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Francisco Merino, Quintauris */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for riscv processor trap handle */ +/* It will do the contex save and call c trap_handler and do contex */ +/* load */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* trap_handler */ +/* */ +/* CALLED BY */ +/* */ +/* hardware exception */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + .global trap_entry + .extern trap_handler + .extern _tx_thread_context_restore + trap_entry: +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, -65*4 // Allocate space for all registers - with floating point enabled +#else + addi sp, sp, -32*4 // Allocate space for all registers - without floating point enabled +#endif + + sw x1, 28*4(sp) // Store RA, 28*4(because call will override ra [ra is a calle register in riscv]) + + call _tx_thread_context_save + + csrr a0, mcause + csrr a1, mepc + csrr a2, mtval + addi sp, sp, -4 + sw ra, 0(sp) + call trap_handler + lw ra, 0(sp) + addi sp, sp, 4 + call _tx_thread_context_restore + // it will nerver return +_err: + wfi + j _err + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level RISC-V32/GNU */ +/* 6.4.x */ +/* AUTHOR */ +/* */ +/* Francisco Merino, Quintauris */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 11-03-2026 Francisco Merino Adapted for RV32 from RV64 port */ +/* */ +/**************************************************************************/ +/* 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: + + .section .text + + la t0, _tx_thread_system_stack_ptr + sw sp, 0(t0) // Save system stack pointer + + la t0, _end // Pickup first free address + la t1, _tx_initialize_unused_memory + sw t0, 0(t1) // Save unused memory address + li t0, MSTATUS_MIE + csrrc zero, mstatus, t0 // clear MSTATUS_MIE bit + li t0, (MSTATUS_MPP_M | MSTATUS_MPIE ) + csrrs zero, mstatus, t0 // set MSTATUS_MPP, MPIE bit + li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE) + csrrs zero, mie, t0 // set mie +#ifdef __riscv_flen + li t0, MSTATUS_FS + csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv + fscsr x0 +#endif + addi sp, sp, -4 + sw ra, 0(sp) + call board_init + lw ra, 0(sp) + addi sp, sp, 4 + la t0, trap_entry + csrw mtvec, t0 + ret diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/uart.c b/ports/risc-v32/gnu/example_build/cva6_ariane/uart.c new file mode 100644 index 00000000..c92c67e6 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/uart.c @@ -0,0 +1,893 @@ +/******************************************************************************* + * Copyright (c) 2020 Thales. + * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + */ +// Additional contributions by: +// Sebastien Jacq - sjthales on github.com +// Anjali Gedam - anjaliigedam on github.com +// +// Description: Driver for UART Ip of the CVA6 platform +// +// =========================================================================== // +// Revisions : +// Date Version Author Description +// 2020-10-06 0.1 S.Jacq modification of the Test for CVA6 softcore +// 2021-07-12 0.2 Anjali G modification for the CVA6 FPGA +// =========================================================================== // + + +#include "uart.h" + +//#include "../plic/plic.h" +//#include "../hw_platform.h" +#define FPGA_UART_0_FREQUENCY 50000000 +#define FPGA_UART_0_BASE (UART_TypeDef *)0x10000000 +#define STDIO_BAUD_RATE UART_115200_BAUD + +/******************************************************************************* + * Defines + */ +#define TX_COMPLETE 0u +#define TX_FIFO_SIZE 16u + +#define FCR_TRIG_LEVEL_MASK 0xC0u + +#define IIRF_MASK 0x0Fu + +#define INVALID_INTERRUPT 0u +#define INVALID_IRQ_HANDLER ((uart_irq_handler_t) 0) +#define NULL_HANDLER ((uart_irq_handler_t) 0) + +#define UART_DATA_READY ((uint8_t) 0x01) + + +/******************************************************************************* + * Possible values for Interrupt Identification Register Field. + */ +#define IIRF_MODEM_STATUS 0x00u +#define IIRF_THRE 0x02u +//#define IIRF_MMI 0x03u +#define IIRF_RX_DATA 0x04u +#define IIRF_RX_LINE_STATUS 0x06u +#define IIRF_DATA_TIMEOUT 0x0Cu + + +//#define PLIC_DEMO 1 +// Source/portable/GCC/RISC-V/portASM.S:290:freertos_risc_v_application_interrupt_handler (weak function : User application can add there own override) + +uart_instance_t g_uart_0 = { .hw_reg = FPGA_UART_0_BASE }; + +/******************************************************************************* + * Global initialization for all modes + */ +static void global_init +( + uart_instance_t * this_uart, + uint32_t baud_rate, + uint8_t line_config +) +{ + + /* disable interrupts */ + this_uart->hw_reg->IER = 0u; + + /* FIFO configuration */ + this_uart->hw_reg->FCR = 0u; + + /* clear receiver FIFO */ + this_uart->hw_reg->FCR = FIFO_RX_TRIGGER_LEVEL_14_MASK | CLEAR_RX_FIFO_MASK | CLEAR_TX_FIFO_MASK | RXRDY_TXRDYN_EN_MASK; + + /* clear transmitter FIFO */ + this_uart->hw_reg->FCR |= CLEAR_TX_FIFO_MASK; + + /* set default READY mode : Mode 0*/ + /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO + * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */ + this_uart->hw_reg->FCR |= RXRDY_TXRDYN_EN_MASK; + + this_uart->hw_reg->MCR = 0u; + + + + /* + * Configure baud rate divisors. This uses the fractional baud rate divisor + * where possible to provide the most accurate baud rat possible. + */ + config_baud_divisors(this_uart, baud_rate); + + /* set the line control register (bit length, stop bits, parity) */ + this_uart->hw_reg->LCR = line_config; + + /* Instance setup */ + this_uart->baudrate = baud_rate; + this_uart->lineconfig = line_config; + this_uart->tx_buff_size = TX_COMPLETE; + this_uart->tx_buffer = (const uint8_t*)0; + this_uart->tx_idx = 0u; + + /* Default handlers for MSS UART interrupts */ + this_uart->rx_handler = NULL_HANDLER; + this_uart->tx_handler = NULL_HANDLER; + this_uart->linests_handler = NULL_HANDLER; + this_uart->modemsts_handler = NULL_HANDLER; + + /* Initialize the sticky status */ + this_uart->status = 0u; +} + +/******************************************************************************* + * Public Functions + *******************************************************************************/ +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_init +( + uart_instance_t* this_uart, + uint32_t baud_rate, + uint8_t line_config +) +{ + /* Perform generic initialization */ + global_init(this_uart, baud_rate, line_config); + + + /* set default tx handler for automated TX using interrupt in USART mode */ + this_uart->tx_handler = default_tx_handler; +} + + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_polled_tx +( + uart_instance_t * this_uart, + const uint8_t * pbuff, + uint32_t tx_size +) +{ + uint32_t char_idx = 0u; + // uint32_t size_sent; + uint8_t status; + //uint32_t temp_tx_size = tx_size; + + //ASSERT(pbuff != ( (uint8_t*)0)); + //ASSERT(tx_size > 0u); + + if ((pbuff != ((uint8_t*)0)) && (tx_size > 0u)) + { + /* Remain in this loop until the entire input buffer + * has been transferred to the UART. + */ + do + { + /* Wait until TX FIFO is empty. */ + do + { + status = this_uart->hw_reg->LSR; + // this_uart->status |= status; + }while (0u == (status & UART_THRE)); + + + /* Check if TX FIFO is empty. */ + // if (status & UART_THRE) + //{ + // uint32_t fill_size = TX_FIFO_SIZE; + + /* Calculate the number of bytes to transmit. */ + //if (temp_tx_size < TX_FIFO_SIZE) + //{ + // fill_size = temp_tx_size; + //} + + /* Fill the TX FIFO with the calculated the number of bytes. */ + //for (size_sent = 0u; size_sent < fill_size; ++size_sent) + //{ + /* Send next character in the buffer. */ + this_uart->hw_reg->THR = pbuff[char_idx]; + char_idx++; + //} + + /* Calculate the number of bytes remaining(not transmitted yet)*/ + //temp_tx_size -= size_sent; + //} + }while (char_idx < tx_size); + } +} + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_polled_tx_string +( + uart_instance_t * this_uart, + const uint8_t * p_sz_string +) +{ + uint32_t char_idx = 0u; + //uint32_t fill_size; + uint8_t data_byte; + volatile uint8_t status; + + //ASSERT(p_sz_string != ((uint8_t*)0)); + + if (p_sz_string != ((uint8_t*)0)) + { + /* Get the first data byte from the input buffer */ + data_byte = p_sz_string[char_idx]; + + /* First check for the NULL terminator byte. + * Then remain in this loop until the entire string in the input buffer + * has been transferred to the UART. + */ + while (0u != data_byte) + { + /* Wait until TX FIFO is empty. */ + do + { + status = this_uart->hw_reg->LSR; + // this_uart->status |= status; + }while (0u == (status & UART_THRE)); + + + /* Send bytes from the input buffer until the TX FIFO is full + * or we reach the NULL terminator byte. + */ + //fill_size = 0u; + + // while ((0u != data_byte) && (fill_size < TX_FIFO_SIZE)) + //{ + /* Send the data byte */ + this_uart->hw_reg->THR = data_byte; + //++fill_size; + char_idx++; + /* Get the next data byte from the input buffer */ + data_byte = p_sz_string[char_idx]; + //} + } + } +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_irq_tx +( + uart_instance_t * this_uart, + const uint8_t * pbuff, + uint32_t tx_size +) +{ + //ASSERT(pbuff != ((uint8_t*)0)); + //ASSERT(tx_size > 0u); + + if ((tx_size > 0u) && (pbuff != ((uint8_t*)0))) + { + /*Initialize the transmit info for the UART instance with the arguments*/ + this_uart->tx_buffer = pbuff; + this_uart->tx_buff_size = tx_size; + this_uart->tx_idx = 0u; + + /* assign default handler for data transfer */ + this_uart->tx_handler = default_tx_handler; + + /* enables TX interrupt */ + this_uart->hw_reg->IER |= ETBEI_MASK; + enable_irq(this_uart); + } +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +int8_t +UART_tx_complete +( + uart_instance_t * this_uart +) +{ + int8_t ret_value = 0; + uint8_t status = 0u; + + /* Read the Line Status Register and update the sticky record. */ + status = this_uart->hw_reg->LSR; + this_uart->status |= status; + + if ((TX_COMPLETE == this_uart->tx_buff_size) && + ((status & UART_TEMT) != 0u)) + { + ret_value = (int8_t)1; + } + + return ret_value; +} + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +size_t +UART_get_rx +( + uart_instance_t * this_uart, + uint8_t * rx_buff, + size_t buff_size +) +{ + size_t rx_size = 0u; + uint8_t status = 0u; + + //ASSERT(rx_buff != ((uint8_t*)0)); + //ASSERT(buff_size > 0u); + //printf("UART_get_rx() called buff_size = %d\n", buff_size); + + if ((rx_buff != (uint8_t*)0) && (buff_size > 0u)) + { + status = this_uart->hw_reg->LSR; + this_uart->status |= status; + //printf("UART_get_rx() LSR status = %d\n", status); + + while (((status & UART_DATA_READY) != 0u) && (rx_size < buff_size)) + { + rx_buff[rx_size] = this_uart->hw_reg->RBR; + ++rx_size; + status = this_uart->hw_reg->LSR; + //printf("1 UART_get_rx() LSR status = %d\n", status); + this_uart->status |= status; + //printf("2 UART_get_rx() LSR status = %d\n", status); + + } + } + + return rx_size; +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_enable_irq +( + uart_instance_t * this_uart, + uart_irq_t irq_mask +) +{ + //ASSERT(UART_INVALID_IRQ > irq_mask); + + enable_irq(this_uart); + + if (UART_INVALID_IRQ > irq_mask) + { + /* irq_mask encoding: 1- enable + * bit 0 - Receive Data Available Interrupt + * bit 1 - Transmitter Holding Register Empty Interrupt + * bit 2 - Receiver Line Status Interrupt + * bit 3 - Modem Status Interrupt + */ + this_uart->hw_reg->IER |= ((uint8_t)(((uint32_t)irq_mask & + (uint32_t)IIRF_MASK))); + + } +} + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_set_rx_handler +( + uart_instance_t * this_uart, + uart_irq_handler_t handler, + uart_rx_trig_level_t trigger_level +) +{ + //ASSERT(handler != INVALID_IRQ_HANDLER ); + //ASSERT(trigger_level < UART_FIFO_INVALID_TRIG_LEVEL); +#ifdef PLIC_DEMO + PLIC_init(); +#endif + + if ((handler != INVALID_IRQ_HANDLER) && + (trigger_level < UART_FIFO_INVALID_TRIG_LEVEL)) + { + //printf("UART DEBUG1\n"); + this_uart->rx_handler = handler; + + /* Set the receive interrupt trigger level. */ + this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR & + (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) | + (uint8_t)trigger_level; + + /* Enable receive interrupt. */ + this_uart->hw_reg->IER |= ERBFI_MASK; + //printf("UART Enable IRQ\n"); + enable_irq(this_uart); + } +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_set_tx_handler +( + uart_instance_t * this_uart, + uart_irq_handler_t handler +) +{ + //ASSERT(handler != INVALID_IRQ_HANDLER); + + if (handler != INVALID_IRQ_HANDLER) + { + this_uart->tx_handler = handler; + + /* Make TX buffer info invalid */ + this_uart->tx_buffer = (const uint8_t*)0; + this_uart->tx_buff_size = 0u; + + /* Enable transmitter holding register Empty interrupt. */ + this_uart->hw_reg->IER |= ETBEI_MASK; + enable_irq(this_uart); + } +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_set_modemstatus_handler +( + uart_instance_t * this_uart, + uart_irq_handler_t handler +) +{ + //ASSERT(handler != INVALID_IRQ_HANDLER); + + if (handler != INVALID_IRQ_HANDLER) + { + this_uart->modemsts_handler = handler; + + /* Enable modem status interrupt. */ + this_uart->hw_reg->IER |= EDSSI_MASK; + enable_irq(this_uart); + } +} + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +size_t +UART_fill_tx_fifo +( + uart_instance_t * this_uart, + const uint8_t * tx_buffer, + size_t tx_size +) +{ + uint8_t status = 0u; + uint32_t size_sent = 0u; + + //ASSERT(tx_buffer != ( (uint8_t*)0)); + //ASSERT(tx_size > 0); + + /* Fill the UART's Tx FIFO until the FIFO is full or the complete input + * buffer has been written. */ + if ((tx_buffer != ((uint8_t*)0)) && (tx_size > 0u)) + { + status = this_uart->hw_reg->LSR; + this_uart->status |= status; + + if (status & UART_THRE) + { + uint32_t fill_size = TX_FIFO_SIZE; + + if (tx_size < TX_FIFO_SIZE) + { + fill_size = tx_size; + } + + /* Fill up FIFO */ + for (size_sent = 0u; size_sent < fill_size; size_sent++) + { + /* Send next character in the buffer. */ + this_uart->hw_reg->THR = tx_buffer[size_sent]; + } + } + } + + return size_sent; +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +uint8_t +UART_get_rx_status +( + uart_instance_t * this_uart +) +{ + uint8_t status = UART_INVALID_PARAM; + + /* + * Extract UART receive error status. + * Bit 1 - Overflow error status + * Bit 2 - Parity error status + * Bit 3 - Frame error status + * Bit 4 - Break interrupt indicator + * Bit 7 - FIFO data error status + */ + this_uart->status |= (this_uart->hw_reg->LSR); + status = (this_uart->status & STATUS_ERROR_MASK); + + //printf("UART_get_rx_status = %d", status); + //printf("UART_get_rx_LSR = %d", this_uart->hw_reg->LSR); + + + /* Clear the sticky status after reading */ + this_uart->status = 0u; + + return status; +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +uint8_t +UART_get_modem_status +( + const uart_instance_t * this_uart +) +{ + uint8_t status = UART_INVALID_PARAM; + + /* + * Extract UART modem status and place in lower bits of "status". + * Bit 0 - Delta Clear to Send Indicator + * Bit 1 - Delta Clear to Receive Indicator + * Bit 2 - Trailing edge of Ring Indicator detector + * Bit 3 - Delta Data Carrier Detect indicator + * Bit 4 - Clear To Send + * Bit 5 - Data Set Ready + * Bit 6 - Ring Indicator + * Bit 7 - Data Carrier Detect + */ + status = this_uart->hw_reg->MSR; + //printf("UART_get_modem_status = %d", status); + + return status; +} + + +/***************************************************************************//** + * UART_get_tx_status. + * See uart.h for details of how to use this function. + */ +uint8_t +UART_get_tx_status +( + uart_instance_t * this_uart +) +{ + uint8_t status = UART_TX_BUSY; + + /* Read the Line Status Register and update the sticky record. */ + status = this_uart->hw_reg->LSR; + this_uart->status |= status; + + /* + * Extract the transmit status bits from the UART's Line Status Register. + * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. + (If = 1, TX FIFO is empty) + * Bit 6 - Transmitter Empty (TEMT) status. + (If = 1, both TX FIFO and shift register are empty) + */ + status &= (UART_THRE | UART_TEMT); + + return status; +} + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_set_break +( + uart_instance_t * this_uart +) +{ + /* set break character on Tx line */ + this_uart->hw_reg->LCR |= SB_MASK; +} + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +void +UART_clear_break +( + uart_instance_t * this_uart +) +{ + /* remove break character from Tx line */ + this_uart->hw_reg->LCR &= ~SB_MASK; +} + +/***************************************************************************//** + * Configure baud divisors using fractional baud rate if possible. + */ +static void +config_baud_divisors +( + uart_instance_t * this_uart, + uint32_t baudrate +) +{ + uint32_t baud_value; + uint32_t baud_value_by_64; + uint32_t baud_value_by_128; +// uint32_t fractional_baud_value; + /* Note that we may need to set this as 64 bits for high frequencies */ + uint32_t pclk_freq; + + this_uart->baudrate = baudrate; + + /* Use the system clock value from hw_platform.h */ + pclk_freq = FPGA_UART_0_FREQUENCY; + + /* + * Compute baud value based on requested baud rate and PCLK frequency. + * The baud value is computed using the following equation: + * baud_value = PCLK_Frequency / (baud_rate * 16) + */ + baud_value_by_128 = (uint32_t)((8UL * pclk_freq) / baudrate); + baud_value_by_64 = baud_value_by_128 / 2u; + baud_value = baud_value_by_64 / 64u; +// fractional_baud_value = baud_value_by_64 - (baud_value * 64u); +// fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) + // - (fractional_baud_value * 2u); + + /* //ASSERT if integer baud value fits in 16-bit. */ + //ASSERT(baud_value <= UINT16_MAX); + + if (baud_value <= (uint32_t)UINT16_MAX) + { + + /* + * Use Fractional baud rate divisors + */ + /* set divisor latch */ + this_uart->hw_reg->LCR = DLAB_MASK; + + /* msb of baud value */ + this_uart->hw_reg->DLM = (uint8_t)(baud_value >> 8); + /* lsb of baud value */ + this_uart->hw_reg->DLL = (uint8_t)baud_value; + + /* reset divisor latch */ + this_uart->hw_reg->LCR = 0; + } +} + +/***************************************************************************//** + * Interrupt service routine triggered by any MSS UART interrupt. This routine + * will call the handler function appropriate to the interrupt from the + * handlers previously registered with the driver through calls to the + * UART_set_*_handler() functions, or it will call the default_tx_handler() + * function in response to transmit interrupts if UART_irq_tx() is used to + * transmit data. + */ +static void __attribute__ ((unused)) +uart_isr +( + uart_instance_t * this_uart +) +{ + //printf("uart_isr called\n"); + uint8_t iirf; + + iirf = this_uart->hw_reg->IIR & IIRF_MASK; + + switch (iirf) + { + case IIRF_MODEM_STATUS: /* Modem status interrupt */ + { + //ASSERT(NULL_HANDLER != this_uart->modemsts_handler); + if (NULL_HANDLER != this_uart->modemsts_handler) + { + (*(this_uart->modemsts_handler))(this_uart); + } + } + break; + + case IIRF_THRE: /* Transmitter Holding Register Empty */ + { + //ASSERT(NULL_HANDLER != this_uart->tx_handler); + if (NULL_HANDLER != this_uart->tx_handler) + { + (*(this_uart->tx_handler))(this_uart); + } + } + break; + + case IIRF_RX_DATA: /* Received Data Available */ + case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */ + { + //ASSERT(NULL_HANDLER != this_uart->rx_handler); + if (NULL_HANDLER != this_uart->rx_handler) + { + (*(this_uart->rx_handler))(this_uart); + } + } + break; + + case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */ + { + //ASSERT(NULL_HANDLER != this_uart->linests_handler); + if (NULL_HANDLER != this_uart->linests_handler) + { + (*(this_uart->linests_handler))(this_uart); + } + } + break; + + default: + { + //ASSERT(INVALID_INTERRUPT); /*Alternative case has been considered*/ + } + break; + } +} + + + +/***************************************************************************//** + * See uart.h for details of how to use this function. + */ +static void +default_tx_handler +( + uart_instance_t * this_uart +) +{ + uint8_t status; + + //ASSERT(( (uint8_t*)0 ) != this_uart->tx_buffer); + //ASSERT(0u < this_uart->tx_buff_size); + + if ((((uint8_t*)0 ) != this_uart->tx_buffer) && + (0u < this_uart->tx_buff_size)) + { + /* Read the Line Status Register and update the sticky record. */ + status = this_uart->hw_reg->LSR; + this_uart->status |= status; + + /* + * This function should only be called as a result of a THRE interrupt. + * Verify that this is true before proceeding to transmit data. + */ + if (status & UART_THRE) + { + uint32_t cnt; + uint32_t fill_size = TX_FIFO_SIZE; + uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx; + + /* Calculate the number of bytes to transmit. */ + if (tx_remain < TX_FIFO_SIZE) + { + fill_size = tx_remain; + } + + /* Fill the TX FIFO with the calculated the number of bytes. */ + for (cnt = 0u; cnt < fill_size; ++cnt) + { + /* Send next character in the buffer. */ + this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx]; + ++this_uart->tx_idx; + } + } + + /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */ + if (this_uart->tx_idx == this_uart->tx_buff_size) + { + this_uart->tx_buff_size = TX_COMPLETE; + + /* disables TX interrupt */ + this_uart->hw_reg->IER &= ~ETBEI_MASK; + } + } +} + + +static void __attribute__ ((unused)) +enable_irq +( + const uart_instance_t * this_uart +) +{ + +#ifdef PLIC_DEMO + PLIC_IRQn_Type plic_num = 0; +#endif + + if (&g_uart_0 == this_uart ) + { + //printf("enable_irq() UART assign plic_num = %d\n",plic_num); +#ifdef PLIC_DEMO + plic_num = UART_0_PLIC_IRQHandler; +#endif + + } + else + { + //printf("ASSERT(0) called\n"); + //ASSERT(0); /*Alternative case has been considered*/ + } + +#ifdef PLIC_DEMO + /* Enable UART instance interrupt in PLIC. */ + PLIC_EnableIRQ(plic_num); +#endif +} + +static void __attribute__ ((unused)) +disable_irq +( + const uart_instance_t * this_uart +) +{ +#ifdef PLIC_DEMO + PLIC_IRQn_Type plic_num = 0; +#endif + + if (&g_uart_0 == this_uart ) + { +#ifdef PLIC_DEMO + plic_num = UART_0_PLIC_IRQHandler; +#endif + } + else + { + //ASSERT(0); /*Alternative case has been considered*/ + } + + /* Disable UART instance interrupt in PLIC. */ +#ifdef PLIC_DEMO + PLIC_DisableIRQ(plic_num); +#endif +} + + +/////////////////////////////////////////////////////////////////////////////////// + +static uart_instance_t * const gp_my_uart = &g_uart_0; + +int uart_init(void) +{ + UART_init(gp_my_uart, STDIO_BAUD_RATE, ( UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT ) ); + + return 0; +} + +int uart_putc(int ch) +{ + UART_polled_tx(gp_my_uart, (const uint8_t *)&ch, 1); +} + +int uart_puts(const char* str) +{ + UART_polled_tx_string(gp_my_uart, str); +}
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/cva6_ariane/uart.h b/ports/risc-v32/gnu/example_build/cva6_ariane/uart.h new file mode 100644 index 00000000..0a835727 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/cva6_ariane/uart.h @@ -0,0 +1,961 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + +#ifndef RISCV_UART_H +#define RISCV_UART_H + +#define UART0 0x10000000L +#define UART0_IRQ 10 + +#define puts(str) uart_puts(str"\n\r") +int uart_init(void); +int uart_putc(int ch); +int uart_puts(const char* str); +#endif + + +/******************************************************************************* + * Copyright (c) 2020 Thales. + * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * + */ +// Additional contributions by: +// Sebastien Jacq - sjthales on github.com +// Anjali Gedam - anjaliigedam on github.com +// +// Description: Driver header for UART Ip of the CVA6 platform +// +// =========================================================================== // +// Revisions : +// Date Version Author Description +// 2020-10-06 0.1 S.Jacq modification of the Test for CVA6 softcore +// 2021-07-12 0.2 Anjali G modification for the CVA6 FPGA +// =========================================================================== // + +#ifndef __UART1_H_ +#define __UART1_H_ 1 + +#include <stddef.h> +#include <stdint.h> + + +/***************************************************************************//** + Baud rates + ========== + The following definitions are used to specify standard baud rates as a + parameter to the UART_init() function. + + | Constant | Description | + |----------------------|------------------| + | UART_110_BAUD | 110 baud rate | + | UART_300_BAUD | 300 baud rate | + | UART_600_BAUD | 600 baud rate | + | UART_1200_BAUD | 1200 baud rate | + | UART_2400_BAUD | 2400 baud rate | + | UART_4800_BAUD | 4800 baud rate | + | UART_9600_BAUD | 9600 baud rate | + | UART_19200_BAUD | 19200 baud rate | + | UART_38400_BAUD | 38400 baud rate | + | UART_57600_BAUD | 57600 baud rate | + | UART_115200_BAUD | 115200 baud rate | + | UART_230400_BAUD | 230400 baud rate | + | UART_460800_BAUD | 460800 baud rate | + | UART_921600_BAUD | 921600 baud rate | + + */ +#define UART_110_BAUD 110U +#define UART_300_BAUD 300U +#define UART_600_BAUD 600U +#define UART_1200_BAUD 1200U +#define UART_2400_BAUD 2400U +#define UART_4800_BAUD 4800U +#define UART_9600_BAUD 9600U +#define UART_19200_BAUD 19200U +#define UART_38400_BAUD 38400U +#define UART_57600_BAUD 57600U +#define UART_115200_BAUD 115200U +#define UART_230400_BAUD 230400U +#define UART_460800_BAUD 460800U +#define UART_921600_BAUD 921600U + +/***************************************************************************//** + Data Bits Length + ================ + The following defines are used to build the value of the UART_init() + function line_config parameter. + + | Constant | Description | + |----------------------|----------------------------| + | UART_DATA_5_BITS | 5 bits of data transmitted | + | UART_DATA_6_BITS | 6 bits of data transmitted | + | UART_DATA_7_BITS | 7 bits of data transmitted | + | UART_DATA_8_BITS | 8 bits of data transmitted | + + */ +#define UART_DATA_5_BITS ((uint8_t) 0x00) +#define UART_DATA_6_BITS ((uint8_t) 0x01) +#define UART_DATA_7_BITS ((uint8_t) 0x02) +#define UART_DATA_8_BITS ((uint8_t) 0x03) + +/***************************************************************************//** + Parity + ====== + The following defines are used to build the value of the UART_init() + function line_config parameter. + + | Constant | Description | + |-------------------------|--------------------------| + | UART_NO_PARITY | No parity | + | UART_ODD_PARITY | Odd Parity | + | UART_EVEN_PARITY | Even parity | + | UART_STICK_PARITY_0 | Stick parity bit to zero | + | UART_STICK_PARITY_1 | Stick parity bit to one | + */ +#define UART_NO_PARITY ((uint8_t) 0x00) +#define UART_ODD_PARITY ((uint8_t) 0x08) +#define UART_EVEN_PARITY ((uint8_t) 0x18) +#define UART_STICK_PARITY_0 ((uint8_t) 0x38) +#define UART_STICK_PARITY_1 ((uint8_t) 0x28) + +/***************************************************************************//** + Number of Stop Bits + =================== + The following defines are used to build the value of the UART_init() + function line_config parameter. + + | Constant | Description | + |---------------------------|--------------------------| + | UART_ONE_STOP_BIT | One stop bit | + | UART_ONEHALF_STOP_BIT | One and a half stop bits | + | UART_TWO_STOP_BITS | Two stop bits | + + */ +#define UART_ONE_STOP_BIT ((uint8_t) 0x00) +#define UART_ONEHALF_STOP_BIT ((uint8_t) 0x04) +#define UART_TWO_STOP_BITS ((uint8_t) 0x04) + +/***************************************************************************//** + Receiver Error Status + ===================== + The following defines are used to determine the UART receiver error type. + These bit mask constants are used with the return value of the + UART_get_rx_status() function to find out if any errors occurred while + receiving data. + + + | Constant | Description | + |------------------------|--------------------------------------------| + | UART_NO_ERROR | No error bit mask (0x00) | + | UART_OVERUN_ERROR | Overrun error bit mask (0x02) | + | UART_PARITY_ERROR | Parity error bit mask (0x04) | + | UART_FRAMING_ERROR | Framing error bit mask (0x08) | + | UART_BREAK_ERROR | Break error bit mask (0x10) | + | UART_FIFO_ERROR | FIFO error bit mask (0x80) | + | UART_INVALID_PARAM | Invalid function parameter bit mask (0xFF) | + */ +#define UART_INVALID_PARAM ((uint8_t)0xFF) +#define UART_NO_ERROR ((uint8_t)0x00 ) +#define UART_OVERUN_ERROR ((uint8_t)0x02) +#define UART_PARITY_ERROR ((uint8_t)0x04) +#define UART_FRAMING_ERROR ((uint8_t)0x08) +#define UART_BREAK_ERROR ((uint8_t)0x10) +#define UART_FIFO_ERROR ((uint8_t)0x80) + + +/******************************************************************************* + * Receiver error status mask. + */ +#define STATUS_ERROR_MASK ( UART_OVERUN_ERROR | UART_PARITY_ERROR | \ + UART_FRAMING_ERROR | UART_BREAK_ERROR | \ + UART_FIFO_ERROR) + +/***************************************************************************//** + Transmitter Status + ================== + The following definitions are used to determine the UART transmitter status. + These bit mask constants are used with the return value of the + UART_get_tx_status() function to find out the status of the transmitter. + + | Constant | Description | + |------------------|----------------------------------------------------| + | UART_TX_BUSY | Transmitter busy (0x00) | + | UART_THRE | Transmitter holding register empty bit mask (0x20) | + | UART_TEMT | Transmitter empty bit mask (0x40) | + + */ +#define UART_TX_BUSY ((uint8_t) 0x00) +#define UART_THRE ((uint8_t) 0x20) +#define UART_TEMT ((uint8_t) 0x40) + +/***************************************************************************//** + Modem Status + ============ + The following defines are used to determine the modem status. These bit + mask constants are used with the return value of the + UART_get_modem_status() function to find out the modem status of + the UART. + + | Constant | Description | + |---------------|-------------------------------------------------| + | UART_DCTS | Delta clear to send bit mask (0x01) | + | UART_DDSR | Delta data set ready bit mask (0x02) | + | UART_TERI | Trailing edge of ring indicator bit mask (0x04) | + | UART_DDCD | Delta data carrier detect bit mask (0x08) | + | UART_CTS | Clear to send bit mask (0x10) | + | UART_DSR | Data set ready bit mask (0x20) | + | UART_RI | Ring indicator bit mask (0x40) | + | UART_DCD | Data carrier detect bit mask (0x80) | + */ +#define UART_DCTS ((uint8_t) 0x01) +#define UART_DDSR ((uint8_t) 0x02) +#define UART_TERI ((uint8_t) 0x04) +#define UART_DDCD ((uint8_t) 0x08) +#define UART_CTS ((uint8_t) 0x10) +#define UART_DSR ((uint8_t) 0x20) +#define UART_RI ((uint8_t) 0x40) +#define UART_DCD ((uint8_t) 0x80) + +/***************************************************************************//** + This typedef specifies the irq_mask parameter for the UART_enable_irq() + and UART_disable_irq() functions. The driver defines a set of bit masks + that are used to build the value of the irq_mask parameter. A bitwise OR of + these bit masks is used to enable or disable multipleUART interrupts. + */ +typedef uint16_t uart_irq_t; + +/***************************************************************************//** + UART Interrupts + ===================== + The following defines specify the interrupt masks to enable and disable + UART interrupts. They are used to build the value of the irq_mask parameter + for the UART_enable_irq() and UART_disable_irq() functions. A bitwise + OR of these constants is used to enable or disable multiple interrupts. + + + | Constant | Description | + |--------------------|---------------------------------------------------------------| + | UART_RBF_IRQ | Receive Data Available Interrupt bit mask (0x001) | + | UART_TBE_IRQ | Transmitter Holding Register Empty interrupt bit mask (0x002) | + | UART_LS_IRQ | Receiver Line Status interrupt bit mask (0x004) | + | UART_MS_IRQ | Modem Status interrupt bit mask (0x008) | + + */ +#define UART_RBF_IRQ 0x001 +#define UART_TBE_IRQ 0x002 +#define UART_LS_IRQ 0x004 +#define UART_MS_IRQ 0x008 +//#define UART_RTO_IRQ 0x010 +//#define UART_NACK_IRQ 0x020 +//#define UART_PIDPE_IRQ 0x040 +//#define UART_LINB_IRQ 0x080 +//#define UART_LINS_IRQ 0x100 +#define UART_INVALID_IRQ UINT16_MAX + +/***************************************************************************//** + This enumeration specifies the receiver FIFO trigger level. This is the number + of bytes that must be received before the UART generates a receive data + available interrupt. It provides the allowed values for the + UART_set_rx_handler() function trigger_level parameter. + */ +typedef enum { + UART_FIFO_SINGLE_BYTE = 0x00, + UART_FIFO_FOUR_BYTES = 0x40, + UART_FIFO_EIGHT_BYTES = 0x80, + UART_FIFO_FOURTEEN_BYTES = 0xC0, + UART_FIFO_INVALID_TRIG_LEVEL + +} uart_rx_trig_level_t; + + + + +/***************************************************************************//** + UART instance type. + This is type definition for UART instance. You need to create and + maintain a record of this type. This holds all data regarding the UART + instance + */ +typedef struct uart_instance uart_instance_t; + +/***************************************************************************//** + Interrupt handler prototype. + This typedef specifies the function prototype for UART interrupt handlers. + All interrupt handlers registered with the UART driver must be of this type. + The interrupt handlers are registered with the driver through the + UART_set_rx_handler(), UART_set_tx_handler(), + UART_set_rxstatus_handler(), and UART_set_modemstatus_handler() + functions. + The this_uart parameter is a pointer to either g_uart0 or g_uart1 to + identify the UART to associate with the handler function. + */ +typedef void (*uart_irq_handler_t)( uart_instance_t * this_uart ); + + +/******************************************************************************* + Register Bit definitions + */ + +/* Line Control register bit definitions */ +#define SB 6u /* Set break */ +#define DLAB 7u /* Divisor latch access bit */ + +/* Line Control register bit masks */ +#define SB_MASK (0x01u << SB) /* Set break */ +#define DLAB_MASK (0x01u << DLAB) /* Divisor latch access bit */ + +/* FIFO Control register bit definitions */ +#define ENABLE_FIFO 0u /* Enable FIFO */ +#define CLEAR_RX_FIFO 1u /* Clear receiver FIFO */ +#define CLEAR_TX_FIFO 2u /* Clear transmitter FIFO */ +#define DMA_MODE 3u /* DMA mode */ +#define FIFO64_ENABLE 5u /* FIFO64 enable */ +#define RDYMODE 3u /* Mode 0 or Mode 1 for TXRDY and RXRDY */ +#define FIFO_RX_TRIGGER 6u /* FIFO RX trigger */ + +/* FIFO Control register bit MASKS */ +#define RXRDY_TXRDYN_EN_MASK (0x01u << 0u) /* Enable TXRDY and RXRDY signals */ +#define CLEAR_RX_FIFO_MASK (0x01u << 1u) /* Clear receiver FIFO */ +#define CLEAR_TX_FIFO_MASK (0x01u << 2u) /* Clear transmitter FIFO */ +#define DMA_MODE_MASK (0x01u << 3u) /* DMA mode */ +#define FIFO64_ENABLE_MASK (0x01u << 5u) /* FIFO64 enable */ +#define RDYMODE_MASK (0x01u << 3u) /* Mode 0 or Mode 1 for TXRDY and RXRDY */ + +#define FIFO_RX_TRIGGER_LEVEL_4_MASK (0x01u << 6u) +#define FIFO_RX_TRIGGER_LEVEL_8_MASK (0x02u << 6u) +#define FIFO_RX_TRIGGER_LEVEL_14_MASK (0x03u << 6u) + +#define FIFO64_RX_TRIGGER_LEVEL_16_MASK (0x01u << 6u) +#define FIFO64_RX_TRIGGER_LEVEL_32_MASK (0x02u << 6u) +#define FIFO64_RX_TRIGGER_LEVEL_56_MASK (0x03u << 6u) + +/* Modem Control register bit definitions */ +//#define LOOP 4u /* Local loopback */ +//#define RLOOP 5u /* Remote loopback */ +//#define ECHO 6u /* Automatic echo */ + +/* Modem Control register bit MASKS */ +//#define LOOP_MASK (0x01u << 4u) /* Local loopback */ +//#define RLOOP_MASK (0x01u << 5u) /* Remote loopback & Automatic echo*/ +//#define ECHO_MASK (0x01u << 6u) /* Automatic echo */ + +/* Line Status register bit definitions */ +#define DR 0u /* Data ready */ +#define THRE 5u /* Transmitter holding register empty */ +#define TEMT 6u /* Transmitter empty */ + +/* Line Status register bit MASKS */ +#define DR_MASK (0x01u << 0u) /* Data ready */ +#define THRE_MASK (0x01u << 5u) /* Transmitter holding register empty */ +#define TEMT_MASK (0x01u << 6u) /* Transmitter empty */ + +/* Interrupt Enable register bit definitions */ +#define ERBFI 0u /* Enable receiver buffer full interrupt */ +#define ETBEI 1u /* Enable transmitter buffer empty interrupt */ +#define ELSI 2u /* Enable line status interrupt */ +#define EDSSI 3u /* Enable modem status interrupt */ + +/* Interrupt Enable register bit MASKS */ +#define ERBFI_MASK (0x01u << 0u) /* Enable receiver buffer full interrupt */ +#define ETBEI_MASK (0x01u << 1u) /* Enable transmitter buffer empty interrupt */ +#define ELSI_MASK (0x01u << 2u) /* Enable line status interrupt */ +#define EDSSI_MASK (0x01u << 3u) /* Enable modem status interrupt */ + +/* Multimode register 0 bit definitions */ +#define ELIN 3u /* Enable LIN header detection */ +#define ETTG 5u /* Enable transmitter time guard */ +#define ERTO 6u /* Enable receiver time-out */ +#define EFBR 7u /* Enable fractional baud rate mode */ + +/* Multimode register 0 bit MASKS */ +#define ELIN_MASK (0x01u << 3u) /* Enable LIN header detection */ +#define ETTG_MASK (0x01u << 5u) /* Enable transmitter time guard */ +#define ERTO_MASK (0x01u << 6u) /* Enable receiver time-out */ +#define EFBR_MASK (0x01u << 7u) /* Enable fractional baud rate mode */ + +/* Multimode register 1 bit definitions */ +#define E_MSB_RX 0u /* MSB / LSB first for receiver */ +#define E_MSB_TX 1u /* MSB / LSB first for transmitter */ +#define EIRD 2u /* Enable IrDA modem */ +#define EIRX 3u /* Input polarity for IrDA modem */ +#define EITX 4u /* Output polarity for IrDA modem */ +#define EITP 5u /* Output pulse width for IrDA modem */ + +/* Multimode register 1 bit MASKS */ +#define E_MSB_RX_MASK (0x01u << 0u) /* MSB / LSB first for receiver */ +#define E_MSB_TX_MASK (0x01u << 1u) /* MSB / LSB first for transmitter */ +#define EIRD_MASK (0x01u << 2u) /* Enable IrDA modem */ +#define EIRX_MASK (0x01u << 3u) /* Input polarity for IrDA modem */ +#define EITX_MASK (0x01u << 4u) /* Output polarity for IrDA modem */ +#define EITP_MASK (0x01u << 5u) /* Output pulse width for IrDA modem */ + +/* Multimode register 2 bit definitions */ +//#define EERR 0u /* Enable ERR / NACK during stop time */ +//#define EAFM 1u /* Enable 9-bit address flag mode */ +//#define EAFC 2u /* Enable address flag clear */ +//#define ESWM 3u /* Enable single wire half-duplex mode */ + +/* Multimode register 2 bit MASKS */ +//#define EERR_MASK (0x01u << 0u) /* Enable ERR / NACK during stop time */ +//#define EAFM_MASK (0x01u << 1u) /* Enable 9-bit address flag mode */ +//#define EAFC_MASK (0x01u << 2u) /* Enable address flag clear */ +//#define ESWM_MASK (0x01u << 3u) /* Enable single wire half-duplex mode */ + +/* Multimode Interrupt Enable register and + Multimode Interrupt Identification register definitions */ +//#define ERTOI 0u /* Enable receiver timeout interrupt */ +//#define ENACKI 1u /* Enable NACK / ERR interrupt */ +//#define EPID_PEI 2u /* Enable PID parity error interrupt */ +//#define ELINBI 3u /* Enable LIN break interrupt */ +//#define ELINSI 4u /* Enable LIN sync detection interrupt */ + +/* Multimode Interrupt Enable register and + Multimode Interrupt Identification register MASKS */ +//#define ERTOI_MASK (0x01u << 0u) /* Enable receiver timeout interrupt */ +//#define ENACKI_MASK (0x01u << 1u) /* Enable NACK / ERR interrupt */ +//#define EPID_PEI_MASK (0x01u << 2u) /* Enable PID parity error interrupt */ +//#define ELINBI_MASK (0x01u << 3u) /* Enable LIN break interrupt */ +//#define ELINSI_MASK (0x01u << 4u) /* Enable LIN sync detection interrupt */ + +typedef struct +{ + union + { + volatile const uint8_t RBR; + volatile uint8_t THR; + volatile uint8_t DLL; + uint32_t RESERVED0; + }; + + union + { + volatile uint8_t DLM; + volatile uint8_t IER; + uint32_t RESERVED1; + }; + + union + { + volatile uint8_t IIR; + volatile uint8_t FCR; + uint32_t RESERVED2; + }; + + volatile uint8_t LCR; + uint8_t RESERVED3[3]; + + volatile uint8_t MCR; + uint8_t RESERVED4[3]; + + volatile const uint8_t LSR; + uint8_t RESERVED5[3]; + + volatile const uint8_t MSR; + uint8_t RESERVED6[3]; + + volatile uint8_t SR; + uint8_t RESERVED7[7]; + +} UART_TypeDef; + + +/***************************************************************************//** + uart_instance. + There is one instance of this structure for each instance of the + microprocessor subsystem's UARTs. Instances of this structure are used to + identify a specific UART. A pointer to an initialized instance of the + uart_instance_t structure is passed as the first parameter to + UART driver functions to identify which UART should perform the + requested operation. + */ +struct uart_instance{ + /* CMSIS related defines identifying the UART hardware. */ + UART_TypeDef * hw_reg; /*!< Pointer to UART registers. */ + uint32_t baudrate; /*!< Operating baud rate. */ + uint8_t lineconfig; /*!< Line configuration parameters. */ + uint8_t status; /*!< Sticky line status. */ + + /* transmit related info (used with interrupt driven transmit): */ + const uint8_t * tx_buffer; /*!< Pointer to transmit buffer. */ + uint32_t tx_buff_size; /*!< Transmit buffer size. */ + uint32_t tx_idx; /*!< Index within transmit buffer of next byte to transmit.*/ + + /* line status interrupt handler:*/ + uart_irq_handler_t linests_handler; /*!< Pointer to user registered line status handler. */ + /* receive interrupt handler:*/ + uart_irq_handler_t rx_handler; /*!< Pointer to user registered receiver handler. */ + /* transmit interrupt handler:*/ + uart_irq_handler_t tx_handler; /*!< Pointer to user registered transmit handler. */ + /* modem status interrupt handler:*/ + uart_irq_handler_t modemsts_handler; /*!< Pointer to user registered modem status handler. */ + + + +}; + +extern uart_instance_t g_uart_0; + +static void default_tx_handler(uart_instance_t * this_uart); +static void enable_irq(const uart_instance_t * this_uart); + +static void disable_irq(const uart_instance_t * this_uart); + +static void config_baud_divisors +( + uart_instance_t * this_uart, + uint32_t baudrate +); + +/***************************************************************************//** + The UART_init() function initializes and configures the + UART with the configuration passed as a parameter. The configuration + parameters are the baud_rate which is used to generate the baud value and the + line_config which is used to specify the line configuration (bit length, + stop bits and parity). + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param baud_rate + The baud_rate parameter specifies the baud rate. It can be specified for + common baud rates using the following defines: + - UART_110_BAUD + - UART_300_BAUD + - UART_600_BAUD + - UART_1200_BAUD + - UART_2400_BAUD + - UART_4800_BAUD + - UART_9600_BAUD + - UART_19200_BAUD + - UART_38400_BAUD + - UART_57600_BAUD + - UART_115200_BAUD + - UART_230400_BAUD + - UART_460800_BAUD + - UART_921600_BAUD + + Alternatively, any nonstandard baud rate can be specified by simply passing + the actual required baud rate as the value for this parameter. + @param line_config + The line_config parameter is the line configuration specifying the bit length, + number of stop bits and parity settings. + + This is a bitwise OR of one value from each of the following groups of + allowed values: + + One of the following to specify the transmit/receive data bit length: + - UART_DATA_5_BITS + - UART_DATA_6_BITS, + - UART_DATA_7_BITS + - UART_DATA_8_BITS + + One of the following to specify the parity setting: + - UART_NO_PARITY + - UART_EVEN_PARITY + - UART_ODD_PARITY + - UART_STICK_PARITY_0 + - UART_STICK_PARITY_1 + + One of the following to specify the number of stop bits: + - UART_ONE_STOP_BIT + - UART_ONEHALF_STOP_BIT + - UART_TWO_STOP_BITS + @return + This function does not return a value. + Example: + @code + #include "uart.h" + int main(void) + { + UART_init(&g_uart0_lo, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + return(0); + } + @endcode + */ +void +UART_init_ariane +( + uart_instance_t* this_uart, + uint32_t baud_rate, + uint8_t line_config +); + +/***************************************************************************//** + The function UART_polled_tx() is used to transmit data. It transfers the + contents of the transmitter data buffer, passed as a function parameter, into + the UART's hardware transmitter FIFO. It returns when the full content of the + transmit data buffer has been transferred to the UART's transmit FIFO. It is + safe to release or reuse the memory used as the transmitter data buffer once + this function returns. + Note: This function reads the UART's line status register (LSR) to poll + for the active state of the transmitter holding register empty (THRE) bit + before transferring data from the data buffer to the transmitter FIFO. It + transfers data to the transmitter FIFO in blocks of 16 bytes or less and + allows the FIFO to empty before transferring the next block of data. + Note: The actual transmission over the serial connection will still be + in progress when this function returns. Use the UART_get_tx_status() + function if you need to know when the transmitter is empty. + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param pbuff + The pbuff parameter is a pointer to a buffer containing the data to + be transmitted. + @param tx_size + The tx_size parameter specifies the size, in bytes, of the data to + be transmitted. + @return + This function does not return a value. + Example: + @code + #include "uart.h" + int main(void) + { + uint8_t message[12] = "Hello World"; + UART_init(&g_uart0_lo, + UART_57600_BAUD, + SS_UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + UART_polled_tx(&g_uart0_lo, message, sizeof(message)); + + return(0); + } + @endcode + */ +void +UART_polled_tx +( + uart_instance_t * this_uart, + const uint8_t * pbuff, + uint32_t tx_size +); + +/***************************************************************************//** + The function UART_polled_tx_string() is used to transmit a NULL ('\0') + terminated string. It transfers the text string, from the buffer starting at + the address pointed to by p_sz_string into the UART's hardware transmitter + FIFO. It returns when the complete string has been transferred to the UART's + transmit FIFO. It is safe to release or reuse the memory used as the string + buffer once this function returns. + Note: This function reads the UART's line status register (LSR) to poll + for the active state of the transmitter holding register empty (THRE) bit + before transferring data from the data buffer to the transmitter FIFO. It + transfers data to the transmitter FIFO in blocks of 16 bytes or less and + allows the FIFO to empty before transferring the next block of data. + Note: The actual transmission over the serial connection will still be + in progress when this function returns. Use the UART_get_tx_status() + function if you need to know when the transmitter is empty. + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param p_sz_string + The p_sz_string parameter is a pointer to a buffer containing the NULL + ('\0') terminated string to be transmitted. + @return + This function does not return a value. + Example: + @code + #include "uart.h" + int main(void) + { + uint8_t message[12] = "Hello World"; + UART_init(&g_uart0_lo, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + UART_polled_tx_string(&g_uart0_lo, message); + + return(0); + } + @endcode + */ +void +UART_polled_tx_string +( + uart_instance_t * this_uart, + const uint8_t * p_sz_string +); + +/***************************************************************************//** + The function UART_irq_tx() is used to initiate an interrupt-driven + transmit. It returns immediately after making a note of the transmit buffer + location and enabling transmit interrupts both at the UART and the PolarFire + SoC Core Complex PLIC level. This function takes a pointer via the pbuff + parameter to a memory buffer containing the data to transmit. The memory + buffer specified through this pointer must remain allocated and contain the + data to transmit until the transmit completion has been detected through calls + to function UART_tx_complete(). The actual transmission over the serial + connection is still in progress until calls to the UART_tx_complete() + function indicate transmit completion. + Note: The UART_irq_tx() function enables both the transmit holding + register empty (THRE) interrupt in the UART and the UART instance + interrupt in the PolarFire SoC Core Complex PLIC as part of its implementation. + Note: The UART_irq_tx() function assigns an internal default transmit + interrupt handler function to the UART's THRE interrupt. This interrupt + handler overrides any custom interrupt handler that you may have previously + registered using the UART_set_tx_handler() function. + Note: The UART_irq_tx() function's default transmit interrupt + handler disables the UART's THRE interrupt when all of the data has + been transferred to the UART's transmit FIFO. + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param pbuff + The pbuff parameter is a pointer to a buffer containing the data + to be transmitted. + @param tx_size + The tx_size parameter specifies the size, in bytes, of the data + to be transmitted. + @return + This function does not return a value. + Example: + @code + #include "uart.h" + int main(void) + { + uint8_t tx_buff[10] = "abcdefghi"; + + UART_init(&g_uart0_lo, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + UART_irq_tx(&g_uart0_lo, tx_buff, sizeof(tx_buff)); + + while(0 == UART_tx_complete(&g_uart0_lo)) + { + ; + } + return(0); + } + @endcode + */ +void +UART_irq_tx +( + uart_instance_t * this_uart, + const uint8_t * pbuff, + uint32_t tx_size +); + +/***************************************************************************//** + The UART_tx_complete() function is used to find out if the + interrupt-driven transmit previously initiated through a call to + UART_irq_tx() is complete. This is typically used to find out when it is + safe to reuse or release the memory buffer holding transmit data. + Note: The transfer of all of the data from the memory buffer to the UART's + transmit FIFO and the actual transmission over the serial connection are both + complete when a call to the UART_tx_complete() function indicates transmit + completion. + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @return + This function return a non-zero value if transmit has completed, otherwise + it returns zero. + Example: + See the UART_irq_tx() function for an example that uses the + UART_tx_complete() function. + */ +int8_t +UART_tx_complete +( + uart_instance_t * this_uart +); + +/***************************************************************************//** + The UART_get_rx() function reads the content of the UART receiver's FIFO + and stores it in the receive buffer that is passed via the rx_buff function + parameter. It copies either the full contents of the FIFO into the receive + buffer, or just enough data from the FIFO to fill the receive buffer, + dependent upon the size of the receive buffer passed by the buff_size + parameter. The UART_get_rx() function returns the number of bytes copied + into the receive buffer .This function is non-blocking and will return 0 + immediately if no data has been received. + Note: The UART_get_rx() function reads and accumulates the receiver + status of the UART instance before reading each byte from the receiver's + data register/FIFO. This allows the driver to maintain a sticky record of any + receiver errors that occur as the UART receives each data byte; receiver + errors would otherwise be lost after each read from the receiver's data + register. A call to the UART_get_rx_status() function returns any receiver + errors accumulated during the execution of the UART_get_rx() function. + Note: If you need to read the error status for each byte received, set + the buff_size to 1 and read the receive line error status for each byte + using the UART_get_rx_status() function. + The UART_get_rx() function can be used in polled mode, where it is called + at regular intervals to find out if any data has been received, or in + interrupt driven-mode, where it is called as part of a receive handler that is + called by the driver as a result of data being received. + Note: In interrupt driven mode you should call the UART_get_rx() + function as part of the receive handler function that you register with + the UART driver through a call to UART_set_rx_handler(). + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param rx_buff + The rx_buff parameter is a pointer to a buffer where the received + data is copied. + @param buff_size + The buff_size parameter specifies the size of the receive buffer in bytes. + @return + This function returns the number of bytes that were copied into the + rx_buff buffer. It returns 0 if no data has been received. + Polled mode example: + @code + int main( void ) + { + uint8_t rx_buff[RX_BUFF_SIZE]; + uint32_t rx_idx = 0; + UART_init(&g_uart0_lo, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + while(1) + { + rx_size = UART_get_rx(&g_uart0_lo, rx_buff, sizeof(rx_buff)); + if(rx_size > 0) + { + process_rx_data(rx_buff, rx_size); + } + task_a(); + task_b(); + } + return 0; + } + @endcode + Interrupt driven example: + @code + int main( void ) + { + UART_init(&g_uart1, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + UART_set_rx_handler(&g_uart1, + uart1_rx_handler, + UART_FIFO_SINGLE_BYTE); + + while(1) + { + task_a(); + task_b(); + } + return 0; + } + void uart1_rx_handler(uart_instance_t * this_uart) + { + uint8_t rx_buff[RX_BUFF_SIZE]; + uint32_t rx_idx = 0; + rx_size = UART_get_rx(this_uart, rx_buff, sizeof(rx_buff)); + process_rx_data(rx_buff, rx_size); + } + @endcode + */ +size_t +UART_get_rx +( + uart_instance_t * this_uart, + uint8_t * rx_buff, + size_t buff_size +); + +/***************************************************************************//** + The UART_set_rx_handler() function is used to register a receive handler + function that is called by the driver when a UART receive data available (RDA) + interrupt occurs. You must create and register the receive handler function + to suit your application and it must include a call to the UART_get_rx() + function to actually read the received data. + Note: The UART_set_rx_handler() function enables both the RDA + interrupt in the UART instance. It also enables the corresponding + UART instance interrupt in the PolarFire SoC Core Complex PLIC as part + of its implementation. + Note: You can disable the RDA interrupt when required by calling the + UART_disable_irq() function. This is your choice and is dependent upon + your application. + + @param this_uart + The this_uart parameter is a pointer to an uart_instance_t + structure identifying the UART hardware block that will perform + the requested function. + @param handler + The handler parameter is a pointer to a receive interrupt handler function + provided by your application that will be called as a result of a UART RDA + interrupt. This handler function must be of type uart_irq_handler_t. + @param trigger_level + The trigger_level parameter is the receive FIFO trigger level. This + specifies the number of bytes that must be received before the UART + triggers an RDA interrupt. + @return + This function does not return a value. + Example: + @code + #include "uart.h" + #define RX_BUFF_SIZE 64 + uint8_t g_rx_buff[RX_BUFF_SIZE]; + void uart0_rx_handler(uart_instance_t * this_uart) + { + UART_get_rx(this_uart, &g_rx_buff[g_rx_idx], sizeof(g_rx_buff)); + } + int main(void) + { + UART_init(&g_uart0_lo, + UART_57600_BAUD, + UART_DATA_8_BITS | UART_NO_PARITY | UART_ONE_STOP_BIT); + + UART_set_rx_handler(&g_uart0_lo, + uart0_rx_handler, + UART_FIFO_SINGLE_BYTE); + + while(1) + { + ; + } + return(0); + } + @endcode + */ +void +UART_set_rx_handler +( + uart_instance_t * this_uart, + uart_irq_handler_t handler, + uart_rx_trig_level_t trigger_level +); + + +#endif /*__UART_H_*/ + diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt b/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt new file mode 100644 index 00000000..43e757ac --- /dev/null +++ b/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt @@ -0,0 +1,45 @@ +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) + +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 +) + +# 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) + add_custom_target(check-functional-riscv32 + COMMAND ${Python3_EXECUTABLE} + ${QEMU_DEMO_DIR}/test/threadx_test_tx_gnu_riscv32_qemu.py + --elf $<TARGET_FILE:kernel.elf> + --qemu qemu-system-riscv32 + --gdb gdb + DEPENDS kernel.elf + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Running RISC-V32 QEMU/GDB functional test runner..." + ) +else() + message(STATUS + "Python3 not found; check-functional-riscv32 target unavailable.") +endif() diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh b/ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh index ba6b4022..d0e092da 100755 --- a/ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh +++ b/ports/risc-v32/gnu/example_build/qemu_virt/build_libthreadx.sh @@ -1,5 +1,35 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + +printf "y\n" | rm -rf ../../../../../build/ +rm -f kernel.elf + pushd ../../../../../ cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_gnu.cmake . cmake --build ./build/ -popd
\ No newline at end of file +popd + +riscv32-unknown-elf-gcc \ + -march=rv32gc -mabi=ilp32d \ + -mcmodel=medany -O0 -g3 -Wall \ + -ffunction-sections -fdata-sections \ + -I../../../../../common/inc \ + -I../../inc \ + entry.S \ + tx_initialize_low_level.S \ + board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \ + -L../../../../../build -lthreadx \ + -T link.lds -nostartfiles \ + -o kernel.elf + + +qemu-system-riscv32 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/csr.h b/ports/risc-v32/gnu/example_build/qemu_virt/csr.h index 9f986bac..b5df6f12 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/csr.h +++ b/ports/risc-v32/gnu/example_build/qemu_virt/csr.h @@ -1,343 +1 @@ -/*************************************************************************** - * Copyright (c) 2025 10xEngineers - * - * This program and the accompanying materials are made available under the - * terms of the MIT License which is available at - * https://opensource.org/licenses/MIT. - * - * SPDX-License-Identifier: MIT - **************************************************************************/ - - -#ifndef RISCV_CSR_H -#define RISCV_CSR_H - - -// Machine Status Register, mstatus -#define MSTATUS_MPP_MASK (3L << 11) // previous mode. -#define MSTATUS_MPP_M (3L << 11) -#define MSTATUS_MPP_S (1L << 11) -#define MSTATUS_MPP_U (0L << 11) -#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. -#define MSTATUS_MPIE (1L << 7) -#define MSTATUS_FS (1L << 13) - -// Machine-mode Interrupt Enable -#define MIE_MTIE (1L << 7) -#define MIE_MSIE (1L << 3) -#define MIE_MEIE (1L << 11) -#define MIE_STIE (1L << 5) // supervisor timer -#define MIE_SSIE (1L << 1) -#define MIE_SEIE (1L << 9) - -// Supervisor Status Register, sstatus -#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User -#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable -#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable -#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable -#define SSTATUS_UIE (1L << 0) // User Interrupt Enable -#define SSTATUS_SPIE (1L << 5) -#define SSTATUS_UPIE (1L << 4) - -// Supervisor Interrupt Enable -#define SIE_SEIE (1L << 9) // external -#define SIE_STIE (1L << 5) // timer -#define SIE_SSIE (1L << 1) // software - -#ifndef __ASSEMBLER__ - -#include <stdint.h> - -static inline uint32_t riscv_get_core() -{ - uint32_t x; - asm volatile("csrr %0, mhartid" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_mstatus() -{ - uint32_t x; - asm volatile("csrr %0, mstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mstatus(uint32_t x) -{ - asm volatile("csrw mstatus, %0" : : "r" (x)); -} - -static inline void riscv_writ_mepc(uint32_t x) -{ - asm volatile("csrw mepc, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sstatus() -{ - uint32_t x; - asm volatile("csrr %0, sstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sstatus(uint32_t x) -{ - asm volatile("csrw sstatus, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sip() -{ - uint32_t x; - asm volatile("csrr %0, sip" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sip(uint32_t x) -{ - asm volatile("csrw sip, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sie() -{ - uint32_t x; - asm volatile("csrr %0, sie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sie(uint32_t x) -{ - asm volatile("csrw sie, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mie() -{ - uint32_t x; - asm volatile("csrr %0, mie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mie(uint32_t x) -{ - asm volatile("csrw mie, %0" : : "r" (x)); -} - -static inline void riscv_writ_sepc(uint32_t x) -{ - asm volatile("csrw sepc, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_sepc() -{ - uint32_t x; - asm volatile("csrr %0, sepc" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_medeleg() -{ - uint32_t x; - asm volatile("csrr %0, medeleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_medeleg(uint32_t x) -{ - asm volatile("csrw medeleg, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mideleg() -{ - uint32_t x; - asm volatile("csrr %0, mideleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mideleg(uint32_t x) -{ - asm volatile("csrw mideleg, %0" : : "r" (x)); -} - -static inline void riscv_writ_stvec(uint32_t x) -{ - asm volatile("csrw stvec, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_stvec() -{ - uint32_t x; - asm volatile("csrr %0, stvec" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_stimecmp() -{ - uint32_t x; - asm volatile("csrr %0, 0x14d" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_stimecmp(uint32_t x) -{ - asm volatile("csrw 0x14d, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_menvcfg() -{ - uint32_t x; - asm volatile("csrr %0, 0x30a" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_menvcfg(uint32_t x) -{ - asm volatile("csrw 0x30a, %0" : : "r" (x)); -} - -static inline void riscv_writ_pmpcfg0(uint32_t x) -{ - asm volatile("csrw pmpcfg0, %0" : : "r" (x)); -} - -static inline void riscv_writ_pmpaddr0(uint32_t x) -{ - asm volatile("csrw pmpaddr0, %0" : : "r" (x)); -} - -static inline void riscv_writ_satp(uint32_t x) -{ - asm volatile("csrw satp, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_satp() -{ - uint32_t x; - asm volatile("csrr %0, satp" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_scause() -{ - uint32_t x; - asm volatile("csrr %0, scause" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_stval() -{ - uint32_t x; - asm volatile("csrr %0, stval" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mcounteren(uint32_t x) -{ - asm volatile("csrw mcounteren, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_mcounteren() -{ - uint32_t x; - asm volatile("csrr %0, mcounteren" : "=r" (x) ); - return x; -} - -static inline uint32_t riscv_get_time() -{ - uint32_t x; - asm volatile("csrr %0, time" : "=r" (x) ); - return x; -} - -static inline void riscv_sintr_on() -{ - uint32_t sstatus = riscv_get_sstatus(); - sstatus |= SSTATUS_SIE; - riscv_writ_sstatus(sstatus); -} - -static inline void riscv_sintr_off() -{ - uint32_t sstatus = riscv_get_sstatus(); - sstatus &= (~SSTATUS_SIE); - riscv_writ_sstatus(sstatus); -} - -static inline int riscv_sintr_get() -{ - uint32_t x = riscv_get_sstatus(); - return (x & SSTATUS_SIE) != 0; -} - -static inline void riscv_sintr_restore(int x) -{ - if(x) - riscv_sintr_on(); - else - riscv_sintr_off(); -} - -static inline void riscv_mintr_on() -{ - uint32_t mstatus = riscv_get_mstatus(); - mstatus |= MSTATUS_MIE; - riscv_writ_mstatus(mstatus); -} - -static inline void riscv_mintr_off() -{ - uint32_t mstatus = riscv_get_mstatus(); - mstatus &= (~MSTATUS_MIE); - riscv_writ_mstatus(mstatus); -} - -static inline int riscv_mintr_get() -{ - uint32_t x = riscv_get_mstatus(); - return (x & MSTATUS_MIE) != 0; -} - -static inline void riscv_mintr_restore(int x) -{ - if(x) - riscv_mintr_on(); - else - riscv_mintr_off(); -} - -static inline uint32_t riscv_get_sp() -{ - uint32_t x; - asm volatile("mv %0, sp" : "=r" (x) ); - return x; -} - -// read and write tp, the thread pointer, which xv6 uses to hold -// this core's hartid (core number), the index into cpus[]. -static inline uint32_t riscv_get_tp() -{ - uint32_t x; - asm volatile("mv %0, tp" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_tp(uint32_t x) -{ - asm volatile("mv tp, %0" : : "r" (x)); -} - -static inline uint32_t riscv_get_ra() -{ - uint32_t x; - asm volatile("mv %0, ra" : "=r" (x) ); - return x; -} - -// flush the TLB. -static inline void sfence_vma() -{ - // the zero, zero means flush all TLB entries. - asm volatile("sfence.vma zero, zero"); -} - -#endif // __ASSEMBLER__ - -#endif +../../../../risc-v_common/inc/csr.h
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c b/ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c index f21dbb26..8288e749 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c +++ b/ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ @@ -9,6 +20,7 @@ #define DEMO_BYTE_POOL_SIZE 9120 #define DEMO_BLOCK_POOL_SIZE 100 #define DEMO_QUEUE_SIZE 100 +float fpu_test_val = 0.0f; char *_to_str(ULONG val) { @@ -201,7 +213,7 @@ UINT status; thread_0_counter++; /* Sleep for 10 ticks. */ - tx_thread_sleep(10); + tx_thread_sleep(1); /* Set event flag 0 to wakeup thread 5. */ status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); @@ -363,6 +375,8 @@ UINT status; if (status != TX_SUCCESS) break; + /* FPU Test */ + fpu_test_val += 1.1f; /* Get the mutex again with suspension. This shows that an owning thread may retrieve the mutex it owns multiple times. */ diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/entry.S b/ports/risc-v32/gnu/example_build/qemu_virt/entry.S new file mode 100644 index 00000000..598a072e --- /dev/null +++ b/ports/risc-v32/gnu/example_build/qemu_virt/entry.S @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + + +.section .text.boot, "ax" +.align 4 +.global _start +.extern main +.extern _sysstack_start +.extern _bss_start +.extern _bss_end +_start: + csrr t0, mhartid + bne t0, zero, 1f + li x1, 0 + li x2, 0 +.option push +.option norelax + la gp, __global_pointer$ /* x3 = gp; norelax keeps this load absolute */ +.option pop + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + la t0, _sysstack_start + li t1, 0x1000 + add sp, t0, t1 + la t0, _bss_start + la t1, _bss_end +_bss_clean_start: + bgeu t0, t1, _bss_clean_end + sb zero, 0(t0) + addi t0, t0, 1 + j _bss_clean_start +_bss_clean_end: + call main +1: + /* todo smp */ + wfi + j 1b diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/entry.s b/ports/risc-v32/gnu/example_build/qemu_virt/entry.s deleted file mode 100644 index 9b202ca1..00000000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/entry.s +++ /dev/null @@ -1,58 +0,0 @@ - -.section .text -.align 4 -.global _start -.extern main -.extern _sysstack_start -.extern _bss_start -.extern _bss_end -_start: - csrr t0, mhartid - bne t0, zero, 1f - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10, 0 - li x11, 0 - li x12, 0 - li x13, 0 - li x14, 0 - li x15, 0 - li x16, 0 - li x17, 0 - li x18, 0 - li x19, 0 - li x20, 0 - li x21, 0 - li x22, 0 - li x23, 0 - li x24, 0 - li x25, 0 - li x26, 0 - li x27, 0 - li x28, 0 - li x29, 0 - li x30, 0 - li x31, 0 - la t0, _sysstack_start - li t1, 0x1000 - add sp, t0, t1 - la t0, _bss_start - la t1, _bss_end -_bss_clean_start: - bgeu t0, t1, _bss_clean_end - sb zero, 0(t0) - addi t0, t0, 1 - j _bss_clean_start -_bss_clean_end: - call main -1: - /* todo smp */ - wfi - j 1b 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 522f90d9..d2ef5f28 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/link.lds +++ b/ports/risc-v32/gnu/example_build/qemu_virt/link.lds @@ -10,6 +10,7 @@ SECTIONS . = 0x80000000; .text : { + KEEP(*(.text.boot)) /* entry.s _start — must be first at 0x80000000 */ *(.text .text.*) . = ALIGN(0x1000); PROVIDE(etext = .); @@ -24,6 +25,9 @@ SECTIONS .data : { . = ALIGN(16); + /* Centre __global_pointer$ in the small-data window so the +/-2 KiB + reach of GP-relative addressing covers the .sdata/.sbss area. */ + PROVIDE( __global_pointer$ = . + 0x800 ); *(.sdata .sdata.*) /* do not need to distinguish this from .data */ . = ALIGN(16); *(.data .data.*) diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/plic.c b/ports/risc-v32/gnu/example_build/qemu_virt/plic.c index 01e5c71a..b247f4fe 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/plic.c +++ b/ports/risc-v32/gnu/example_build/qemu_virt/plic.c @@ -1,72 +1 @@ -#include "plic.h" -#include <stddef.h> -irq_callback callbacks[MAX_CALLBACK_NUM]; - -void plic_irq_enable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno)); - return; -} - -void plic_irq_disable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno))); - return; -} - -void plic_prio_set(int irqno, int prio) -{ - PLIC_SET_PRIO(irqno, prio); -} - -int plic_prio_get(int irqno) -{ - return PLIC_GET_PRIO(irqno); -} - -int plic_register_callback(int irqno, irq_callback callback) -{ - if(!(irqno >=0 && irqno < MAX_CALLBACK_NUM)) - return -1; - callbacks[irqno] = callback; - return 0; -} - -int plic_unregister_callback(int irqno) -{ - return plic_register_callback(irqno, NULL); -} - -int plic_init(void) -{ - for(int i=0;i<MAX_CALLBACK_NUM;i++) - { - callbacks[i] = NULL; - } - return 0; -} - -int plic_claim(void) -{ - int hart = riscv_get_core(); - return (*(uint32_t*)PLIC_MCLAIM(hart)); -} - -void plic_complete(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; - return; -} - -int plic_irq_intr(void) -{ - int ret = -1; - int irqno = plic_claim(); - if(callbacks[irqno] != NULL) - ret = (callbacks[irqno])(irqno); - plic_complete(irqno); - return ret; -} +../../../../risc-v_common/example_build/plic/plic.c
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/plic.h b/ports/risc-v32/gnu/example_build/qemu_virt/plic.h index f505e608..f776a3d2 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/plic.h +++ b/ports/risc-v32/gnu/example_build/qemu_virt/plic.h @@ -1,49 +1 @@ -/*************************************************************************** - * Copyright (c) 2025 10xEngineers - * - * This program and the accompanying materials are made available under the - * terms of the MIT License which is available at - * https://opensource.org/licenses/MIT. - * - * SPDX-License-Identifier: MIT - **************************************************************************/ - -#ifndef RISCV_PLIC_H -#define RISCV_PLIC_H - -#include "csr.h" -#include <stdint.h> - -#define PLIC 0x0c000000L -#define PLIC_PRIORITY (PLIC + 0x0) -#define PLIC_PENDING (PLIC + 0x1000) -#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100) -#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100) -#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000) -#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000) -#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000) -#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000) -#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 MAX_CALLBACK_NUM 128 -typedef int (*irq_callback)(int irqno); - -void plic_irq_enable(int irqno); -void plic_irq_disable(int irqno); -int plic_prio_get(int irqno); -void plic_prio_set(int irqno, int prio); -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 - +../../../../risc-v_common/example_build/plic/plic.h
\ No newline at end of file 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 new file mode 100644 index 00000000..6123cd73 --- /dev/null +++ b/ports/risc-v32/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv32_qemu.py @@ -0,0 +1,295 @@ +############################################################################## +# 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 +############################################################################## + +import subprocess +import sys +import os +import argparse +import socket +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 + +def get_free_port(): + """Finds a free 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. + """ + print(f"Testing ELF: {elf_path}") + print(f"QEMU: {qemu_bin}") + print(f"GDB: {gdb_bin}") + + # Find a free port for GDB connection + gdb_port = get_free_port() + print(f"Using GDB port: {gdb_port}") + + # 1. Start QEMU in the background + qemu_cmd = [ + qemu_bin, + "-M", "virt", + "-nographic", + "-bios", "none", # Disable default OpenSBI to avoid overlap 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 + ] + + print(f"Starting QEMU: {' '.join(qemu_cmd)}") + qemu_process = subprocess.Popen( + qemu_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + if qemu_process.poll() is not None: + print("QEMU failed to start.") + print(qemu_process.stderr.read()) + return False + + # 2. Create a GDB command file + # We use a defined command for the timer interrupt to perform the check automatically + gdb_cmds = """ +file {elf} +target remote :{port} +set pagination off +set confirm off + +# Setup Breakpoints +break tx_application_define +break thread_0_entry +break thread_6_and_7_entry +break _tx_timer_interrupt + +# Execute to Application Definition +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 +print/x $mstatus +info registers float +print fpu_test_val + +# Await Timer Interrupt +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 +set $ret_addr = $ra +tbreak *$ret_addr +continue + +# 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 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" + else + printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED\\n" + end +else + printf "PREEMPT_VERIFIED_FAIL_NULL\\n" +end + +quit +""".format(port=gdb_port, elf=elf_path) + + gdb_cmd_file = "test_cmds.gdb" + with open(gdb_cmd_file, "w") as f: + f.write(gdb_cmds) + + # 3. Run GDB + gdb_cmd = [ + gdb_bin, + "--batch", + "-x", gdb_cmd_file + ] + + 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 + + try: + gdb_process = subprocess.run( + gdb_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + timeout=GDB_TIMEOUT_S, + ) + + print_content("GDB Output:") + print_content(gdb_process.stdout) + if gdb_process.stderr: + print_content("GDB Error Output:") + print_content(gdb_process.stderr) + + except subprocess.TimeoutExpired as e: + print_content( + f"FAILURE: GDB session exceeded {GDB_TIMEOUT_S}s timeout; " + "likely stuck on a `continue` that never matched a breakpoint." + ) + if e.stdout: + print_content("GDB Output (partial):") + print_content(e.stdout if isinstance(e.stdout, str) + else e.stdout.decode(errors='replace')) + if e.stderr: + print_content("GDB Error Output (partial):") + print_content(e.stderr if isinstance(e.stderr, str) + else e.stderr.decode(errors='replace')) + return False + + except Exception as e: + print_content(f"An error occurred during test execution: {e}") + return False + + finally: + # 4. Clean up + 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.") + qemu_process.kill() + + # Verify results + stdout = gdb_process.stdout + timer_hit = "Breakpoint 4, _tx_timer_interrupt" in stdout + fpu_verified = False + 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: + print_content("SUCCESS: FPU instructions executed and registers inspected.") + fpu_verified = True + else: + print_content("FAILURE: Hit thread, but failed to inspect FPU. Output does not contain expected value.") + + if timer_hit: + print_content("SUCCESS: Timer Interrupt verified! Hit _tx_timer_interrupt.") + else: + print_content("FAILURE: Did not hit timer interrupt.") + + if preemption_verified: + print_content("SUCCESS: Preemption verified (higher-priority thread " + "preempted a lower-priority one).") + else: + if "PREEMPT_VERIFIED_FAIL_INVERTED" in stdout: + print_content("FAILURE: Preemption inverted -- lower priority " + "thread scheduled over higher priority one.") + elif "PREEMPT_VERIFIED_FAIL_NULL" in stdout: + print_content("FAILURE: Preemption check saw NULL thread pointers.") + elif "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED" in stdout: + print_content("FAILURE: Preemption was not observed within the " + "loop budget.") + else: + print_content("FAILURE: Preemption check did not run to completion.") + + if timer_hit and fpu_verified and preemption_verified: + return True + else: + return False + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Run ThreadX QEMU/GDB Test") + 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") + + args = parser.parse_args() + + success = run_qemu_test(args.elf, args.qemu, args.gdb) + + if success: + sys.exit(0) + else: + sys.exit(1) diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/trap.c b/ports/risc-v32/gnu/example_build/qemu_virt/trap.c index a2733e02..bdce3305 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/trap.c +++ b/ports/risc-v32/gnu/example_build/qemu_virt/trap.c @@ -1,67 +1 @@ -#include "csr.h" -#include <stdint.h> -#include "uart.h" -#include "hwtimer.h" -#include "plic.h" -#include <tx_port.h> -#include <tx_api.h> - -#define OS_IS_INTERUPT(mcause) (mcause & 0x80000000u) -#define OS_IS_EXCEPTION(mcause) (~(OS_IS_INTERUPT)) -#define OS_IS_TICK_INT(mcause) (mcause == 0x80000007u) -#define OS_IS_SOFT_INT(mcause) (mcause == 0x80000003u) -#define OS_IS_EXT_INT(mcause) (mcause == 0x8000000bu) -#define OS_IS_TRAP_USER(mcause) (mcause == 0x0000000bu) -extern void _tx_timer_interrupt(void); - -extern int uart_putc(int ch); - -static void print_hex(uintptr_t val) -{ - char digits[] = "0123456789ABCDEF"; - uart_putc('0'); - uart_putc('x'); - for(int i = (sizeof(uintptr_t)*2) - 1; i >= 0; i--) { - int d = (val >> (i*4)) & 0xF; - uart_putc(digits[d]); - } - uart_putc('\n'); -} - -void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) -{ - // uart_puts("DEBUG : threadx/ports/risc-v32/gnu/example_build/qemu_virt/trap.c, trap_handler\n"); - if(OS_IS_INTERUPT(mcause)) - { - if(OS_IS_TICK_INT(mcause)) - { - hwtimer_handler(); - _tx_timer_interrupt(); - } - else if(OS_IS_EXT_INT(mcause)) - { - int ret = plic_irq_intr(); - if(ret) - { - puts("[INTERRUPT]: handler irq error!"); - while(1) ; - } - } - else - { - puts("[INTERRUPT]: now can't deal with the interrupt!"); - while(1) ; - } - } - else - { - puts("[EXCEPTION] : Unkown Error!!"); - puts("mcause:"); - print_hex(mcause); - puts("mepc:"); - print_hex(mepc); - puts("mtval:"); - print_hex(mtval); - while(1) ; - } -} +../../../../risc-v_common/example_build/trap/trap_qemu.c
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/uart.c b/ports/risc-v32/gnu/example_build/qemu_virt/uart.c index a175b7d2..1666c8c8 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/uart.c +++ b/ports/risc-v32/gnu/example_build/qemu_virt/uart.c @@ -1,102 +1 @@ -#include "uart.h" -#include "csr.h" -#include "plic.h" -#include <stdint.h> - -// the UART control registers are memory-mapped -// at address UART0. this macro returns the -// address of one of the registers. -#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg))) - -// the UART control registers. -// some have different meanings for -// read vs write. -// see http://byterunner.com/16550.html -#define RHR 0 // receive holding register (for input bytes) -#define THR 0 // transmit holding register (for output bytes) -#define IER 1 // interrupt enable register -#define IER_RX_ENABLE (1<<0) -#define IER_TX_ENABLE (1<<1) -#define FCR 2 // FIFO control register -#define FCR_FIFO_ENABLE (1<<0) -#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs -#define ISR 2 // interrupt status register -#define LCR 3 // line control register -#define LCR_EIGHT_BITS (3<<0) -#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate -#define LSR 5 // line status register -#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR -#define LSR_TX_IDLE (1<<5) // THR can accept another character to send - -#define ReadReg(reg) (*(Reg(reg))) -#define WriteReg(reg, v) (*(Reg(reg)) = (v)) - -int uart_init(void) -{ - // disable interrupts. - WriteReg(IER, 0x00); - - // special mode to set baud rate. - WriteReg(LCR, LCR_BAUD_LATCH); - - // LSB for baud rate of 38.4K. - WriteReg(0, 0x03); - - // MSB for baud rate of 38.4K. - WriteReg(1, 0x00); - - // leave set-baud mode, - // and set word length to 8 bits, no parity. - WriteReg(LCR, LCR_EIGHT_BITS); - - // reset and enable FIFOs. - WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); - - // enable transmit and receive interrupts. - // WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE); - - //enable UART0 in PLIC - plic_irq_enable(UART0_IRQ); - - //set UART0 priority in PLIC - plic_prio_set(UART0_IRQ, 1); - - //register callback for UART0 - //plic_register_callback(UART0_IRQ, uart_intr); - puts("[UART0] : Uart Init Done, this is Test output!"); - return 0; -} - -void uart_putc_nolock(int ch) -{ - // wait for Transmit Holding Empty to be set in LSR. - while((ReadReg(LSR) & LSR_TX_IDLE) == 0) - ; - WriteReg(THR, ch); - return; -} - -int uart_putc(int ch) -{ - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - uart_putc_nolock(ch); - riscv_mintr_restore(intr_enable); - return 1; -} - -int uart_puts(const char* str) -{ - int i; - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - for(i=0;str[i]!=0;i++) - { - uart_putc_nolock(str[i]); - } - uart_putc_nolock('\n'); - riscv_mintr_restore(intr_enable); - return i; -} - - +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.c
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/uart.h b/ports/risc-v32/gnu/example_build/qemu_virt/uart.h index debfd9df..aba5ae7b 100644..120000 --- a/ports/risc-v32/gnu/example_build/qemu_virt/uart.h +++ b/ports/risc-v32/gnu/example_build/qemu_virt/uart.h @@ -1,23 +1 @@ -/*************************************************************************** - * 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 - **************************************************************************/ - -#ifndef RISCV_UART_H -#define RISCV_UART_H - -#define UART0 0x10000000L -#define UART0_IRQ 10 - -#define puts uart_puts -int uart_init(void); -int uart_putc(int ch); -void uart_putc_nolock(int ch); -int uart_puts(const char* str); -#endif +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.h
\ No newline at end of file diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh index ff9bb930..ff983efe 100755 --- a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_libthreadx.sh @@ -1,4 +1,15 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + pushd ../../../../../ rm -rf build diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh index ec91e36a..cc0b6a67 100755 --- a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/build_threadx_sample.sh @@ -1,4 +1,15 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + bash build_libthreadx.sh diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h index e69de29b..054d0844 100644 --- a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/chip_riscv_dummy/include/dw_uart.h @@ -0,0 +1,11 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h index 9f65050c..5a09070c 100755 --- a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/components/csi/csi2/include/drv/list.h @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + #ifndef AOS_LIST_H #define AOS_LIST_H diff --git a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c index 3df2c251..f8a6d82c 100644 --- a/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c +++ b/ports/risc-v32/gnu/example_build/xuantie_smartl_fpga/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/risc-v32/gnu/inc/tx_port.h b/ports/risc-v32/gnu/inc/tx_port.h index ed014675..baf14be9 100644 --- a/ports/risc-v32/gnu/inc/tx_port.h +++ b/ports/risc-v32/gnu/inc/tx_port.h @@ -47,228 +47,109 @@ #ifndef TX_PORT_H #define TX_PORT_H -#ifndef __ASSEMBLER__ - -/* Include for memset. */ -#include <string.h> - +/* Include shared RISC-V32 port definitions common to all toolchain ports. */ +#include "../../common/tx_port_riscv32_common.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 */ - -#endif /* __ASSEMBLER__ */ - - -/* Define ThreadX basic types for this port. */ - -#define VOID void +/* Define automated coverage test extensions for the ThreadX regression test. */ #ifndef __ASSEMBLER__ -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 -#endif /* __ASSEMBLER__ */ - - - -/* 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 +typedef unsigned int TEST_FLAG; +extern TEST_FLAG threadx_byte_allocate_loop_test; +extern TEST_FLAG threadx_byte_release_loop_test; +extern TEST_FLAG threadx_mutex_suspension_put_test; +extern TEST_FLAG threadx_mutex_suspension_priority_test; +#ifndef TX_TIMER_PROCESS_IN_ISR +extern TEST_FLAG threadx_delete_timer_thread; #endif - -/* 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 1024 /* Minimum stack size for this port */ +extern void abort_and_resume_byte_allocating_thread(void); +extern void abort_all_threads_suspended_on_mutex(void); +extern void suspend_lowest_priority(void); +#ifndef TX_TIMER_PROCESS_IN_ISR +extern void delete_timer_thread(void); #endif +extern TEST_FLAG test_stack_analyze_flag; +extern TEST_FLAG test_initialize_flag; +extern TEST_FLAG test_forced_mutex_timeout; -/* 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 RISC-V port. */ - -#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ -#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */ - - -/* 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. */ - -#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. */ - -#define TX_INLINE_INITIALIZATION +#ifdef TX_REGRESSION_TEST +#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \ + { \ + pool_ptr -> tx_byte_pool_owner = TX_NULL; \ + threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \ + } -/* 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. */ - -#define TX_THREAD_EXTENSION_0 -#define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 -#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 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 TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \ + { \ + threadx_byte_release_loop_test = ((TEST_FLAG) 0); \ + abort_and_resume_byte_allocating_thread(); \ + } +#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \ + abort_all_threads_suspended_on_mutex(); \ + } -/* Define the ThreadX object deletion extensions for the remaining objects. */ +#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \ + { \ + test_forced_mutex_timeout = ((TEST_FLAG) 0); \ + _tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \ + } -#define TX_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 TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \ + suspend_lowest_priority(); \ + } +#ifndef TX_TIMER_PROCESS_IN_ISR -/* Define 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. */ +#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \ + { \ + threadx_delete_timer_thread = ((TEST_FLAG) 0); \ + delete_timer_thread(); \ + (a) = ((UINT) 1); \ + } -/* Expose helper used to perform an atomic read/modify/write of mstatus. - The helper composes and returns the posture per ThreadX contract. */ -#ifndef __ASSEMBLER__ -UINT _tx_thread_interrupt_control(UINT new_posture); #endif -#ifdef TX_DISABLE_INLINE - -#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; - -#define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory"); -#define TX_RESTORE { \ - unsigned long _temp_mstatus; \ - __asm__ volatile( \ - "csrc mstatus, 8\n" \ - "andi %0, %1, 8\n" \ - "csrs mstatus, %0" \ - : "=&r" (_temp_mstatus) \ - : "r" (interrupt_save) \ - : "memory"); \ +#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \ + { \ + thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \ + { \ + stack_ptr = thread_ptr -> tx_thread_stack_start; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \ + { \ + *stack_ptr = TX_STACK_FILL; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else \ + { \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ } -#else - -#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; - -#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE); -#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save); - -#endif /* TX_DISABLE_INLINE */ - +#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \ + { \ + test_initialize_flag = ((TEST_FLAG) 0); \ + return; \ + } -/* Define the interrupt lockout macros for each ThreadX object. */ +#endif /* TX_REGRESSION_TEST */ -#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 +#endif /* __ASSEMBLER__ */ /* Define the version ID of ThreadX. This may be utilized by the application. */ @@ -276,7 +157,7 @@ UINT _tx_thread_interrupt_control(UIN #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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ 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 703466bd..2940f215 100644 --- a/ports/risc-v32/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v32/gnu/src/tx_initialize_low_level.S @@ -62,7 +62,7 @@ __tx_free_memory_start: /**************************************************************************/ /* VOID _tx_initialize_low_level(VOID) { */ - .global _tx_initialize_low_level + .weak _tx_initialize_low_level .weak _tx_initialize_low_level _tx_initialize_low_level: 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 73a07f61..d3d449e4 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_restore.S @@ -29,6 +29,7 @@ /* AUTHOR */ /* */ /* Akif Ejaz, 10xEngineers */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -82,7 +83,13 @@ _tx_thread_context_restore: /* Just recover the saved registers and return to the point of interrupt. */ - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || 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 @@ -130,6 +137,7 @@ _tx_thread_context_restore: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_skip_fp_restore: /* Recover standard registers. */ @@ -149,7 +157,7 @@ _tx_thread_context_restore: /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */ li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode (bits 12:11) + li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, preserve everything except the bits we will modify. */ @@ -222,7 +230,13 @@ _tx_thread_no_preempt_restore: lw sp, 8(t1) // Switch back to thread's stack - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || 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 @@ -270,6 +284,7 @@ _tx_thread_no_preempt_restore: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_no_preempt_skip_fp_restore: /* Recover the saved context and return to the point of interrupt. */ @@ -284,7 +299,7 @@ _tx_thread_no_preempt_restore: csrr t1, mstatus li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode + li t3, 0x1880 // Set MPP=Machine (0x1800) + MPIE=1 (0x80); mret sets MIE=MPIE li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE and t1, t1, t4 or t1, t1, t3 @@ -331,7 +346,13 @@ _tx_thread_preempt_restore: ori t3, zero, 1 // Build interrupt stack type sw t3, 0(t0) // Store stack type - /* Store floating point preserved registers. */ + /* Store floating point preserved registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || 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 @@ -359,6 +380,7 @@ _tx_thread_preempt_restore: fsd f26, 57*4(t0) // Store fs10 fsd f27, 58*4(t0) // Store fs11 #endif +_tx_thread_preempt_skip_fp_restore: /* Store standard preserved registers. */ 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 66402934..0a0c0c15 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -29,6 +29,7 @@ /* AUTHOR */ /* */ /* Akif Ejaz, 10xEngineers */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -96,6 +97,15 @@ _tx_thread_context_save: sw t5, 14*4(sp) // Store t5 sw t6, 13*4(sp) // Store t6 + /* 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) + 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 @@ -144,14 +154,11 @@ _tx_thread_context_save: csrr t0, fcsr sw t0, 63*4(sp) // Store fcsr #endif +_tx_thread_skip_fpu_save: csrr t0, mepc sw t0, 30*4(sp) // Save it on the stack - /* Save mstatus. */ - csrr t0, mstatus - sw t0, 29*4(sp) - la t1, _tx_thread_current_ptr // Pickup address of current thread ptr lw t2, 0(t1) // Pickup current thread pointer beqz t2, _tx_thread_idle_system_save // If NULL, idle system was interrupted @@ -190,6 +197,15 @@ _tx_thread_nested_save: sw t5, 14*4(sp) // Store t5 sw t6, 13*4(sp) // Store t6 + /* 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) + 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 @@ -238,13 +254,11 @@ _tx_thread_nested_save: csrr t0, fcsr sw t0, 63*4(sp) // Store fcsr #endif +_tx_thread_skip_nested_fpu_save: csrr t0, mepc sw t0, 30*4(sp) // Save it on stack - csrr t0, mstatus - sw t0, 29*4(sp) - /* Call the ISR execution exit function if enabled. */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY call _tx_execution_isr_enter // Call the ISR execution enter function diff --git a/ports/risc-v32/gnu/src/tx_thread_schedule.S b/ports/risc-v32/gnu/src/tx_thread_schedule.S index 1c235a2d..79bfd51a 100644 --- a/ports/risc-v32/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v32/gnu/src/tx_thread_schedule.S @@ -133,7 +133,12 @@ _tx_thread_ready_to_run: lw t0, 0(sp) // Pickup stack type beqz t0, _tx_thread_solicited_return // If 0, solicited return - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || 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 @@ -205,9 +210,10 @@ _tx_thread_ready_to_run: lw t0, 63*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_skip_fp_restore: +#endif /* Recover standard registers. */ - lw t0, 30*4(sp) // Recover mepc csrw mepc, t0 // Setup mepc @@ -256,7 +262,12 @@ _tx_thread_ready_to_run: _tx_thread_solicited_return: - /* Recover floating point registers. */ + /* Recover floating point registers only if saved mstatus.FS was not Off. */ +#if defined(__riscv_float_abi_single) || 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 @@ -288,10 +299,11 @@ _tx_thread_solicited_return: lw t0, 27*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_solicited_skip_fp_restore: +#endif /* Recover standard registers. */ - - lw t0, 14*4(sp) // Recover mstatus + lw t0, 14*4(sp) // Reload saved mstatus (t0 may hold fcsr if FP was restored) csrw mstatus, t0 // Restore mstatus lw ra, 13*4(sp) // Recover return address 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 4090e7b2..20ff25f2 100644 --- a/ports/risc-v32/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v32/gnu/src/tx_thread_system_return.S @@ -69,7 +69,17 @@ _tx_thread_system_return: addi sp, sp, -16*4 // Allocate space on the stack - without floating point enabled #endif - /* Store floating point preserved registers. */ + sw zero, 0(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) + 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 @@ -101,8 +111,9 @@ _tx_thread_system_return: csrr t0, fcsr sw t0, 27*4(sp) // Store fcsr #endif +_tx_thread_system_return_skip_fp: +#endif - sw zero, 0(sp) // Solicited stack type sw ra, 13*4(sp) // Save return address sw s0, 12*4(sp) // Save s0 sw s1, 11*4(sp) // Save s1 @@ -116,9 +127,6 @@ _tx_thread_system_return: sw s9, 3*4(sp) // Save s9 sw s10, 2*4(sp) // Save s10 sw s11, 1*4(sp) // Save s11 - csrr t0, mstatus // Pickup mstatus - sw t0, 14*4(sp) // Save mstatus - /* Lockout interrupts. will be enabled in _tx_thread_schedule */ diff --git a/ports/risc-v32/iar/example_build/sample_threadx.c b/ports/risc-v32/iar/example_build/sample_threadx.c index 3c6d2587..13128282 100644 --- a/ports/risc-v32/iar/example_build/sample_threadx.c +++ b/ports/risc-v32/iar/example_build/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. Please refer to Chapter 6 of the ThreadX User Guide for a complete diff --git a/ports/risc-v64/gnu/CMakeLists.txt b/ports/risc-v64/gnu/CMakeLists.txt index 9357c697..e51de735 100644 --- a/ports/risc-v64/gnu/CMakeLists.txt +++ b/ports/risc-v64/gnu/CMakeLists.txt @@ -1,19 +1,6 @@ +include(${CMAKE_CURRENT_LIST_DIR}/../../../cmake/threadx_riscv_port.cmake) -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_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 +threadx_add_riscv_port( + SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src + INC_DIR ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/.gitignore b/ports/risc-v64/gnu/example_build/bananapi-f3/.gitignore new file mode 100644 index 00000000..9cae8f84 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/.gitignore @@ -0,0 +1,4 @@ +kernel.bin +kernel.elf +kernel.uImage + diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/board.c b/ports/risc-v64/gnu/example_build/bananapi-f3/board.c new file mode 100644 index 00000000..efdbfe6d --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/board.c @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "plic.h" +#include "hwtimer.h" +#include "uart.h" +#include <stdint.h> +#include <stddef.h> + +void *memset(void *des, int c, size_t n) +{ + if ((des == NULL) || n == 0) + return des; + + char *t = (char *)des; + for (size_t i = 0; i < n; i++) + t[i] = c; + return t; +} + +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/bananapi-f3/build_libthreadx.sh b/ports/risc-v64/gnu/example_build/bananapi-f3/build_libthreadx.sh new file mode 100755 index 00000000..2c94b8a1 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/build_libthreadx.sh @@ -0,0 +1,70 @@ +#!/bin/bash +############################################################################## +# 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 +############################################################################## + +# Build the bananapi-f3 (SpacemiT K1) ThreadX kernel. +# +# Boot flow: FSBL -> OpenSBI (M-mode) -> U-Boot (S-mode) -> ThreadX (S-mode). +# +# OpenSBI runs in M-mode and delegates S-mode to the next stage. +# U-Boot runs in S-mode; any code launched from U-Boot also runs in S-mode. +# +# Use the TX_RISCV_SMODE CMake option to build libthreadx.a for S-mode. +# +# This libthreadx.a (S-mode), then links the BSP objects +# to produce kernel.elf / kernel.bin. + +set -e + +# Where ThreadX is loaded by U-Boot (${loadaddr}). Must match the link.lds origin. +LOAD_ADDR=0x00200000 + +# printf "y\n" | rm -rf ../../../../../build/ +rm -f kernel.elf kernel.bin kernel.uImage + +pushd ../../../../../ +cmake -Bbuild -GNinja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake \ + -DTX_USER_FILE="" \ + -DTX_RISCV_SMODE=ON \ + . +cmake --build ./build/ +popd + +riscv64-unknown-elf-gcc \ + -march=rv64gc -mabi=lp64d \ + -mcmodel=medany -O0 -g3 -Wall \ + -DTX_RISCV_SMODE \ + -ffunction-sections -fdata-sections \ + -I../../../../../common/inc \ + -I../../inc \ + entry.S \ + tx_initialize_low_level.S \ + board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \ + -L../../../../../build -lthreadx \ + -T link.lds -nostartfiles \ + -o kernel.elf + +# Strip ELF metadata down to the loadable bytes. +riscv64-unknown-elf-objcopy -O binary kernel.elf kernel.bin + +echo "== Build artifacts ==" +ls -la kernel.elf kernel.bin 2>/dev/null || true +echo +riscv64-unknown-elf-size kernel.elf || true +echo + +# Run on Bananapi BPI-F3 +# Stop the boot at U-Boot (press reset button and press "s" key continuously to stop autoboot). +# at "=>" prompt, load the kernel using the following commands: +# +# " ELF: tftpboot ${loadaddr} kernel.elf && bootelf ${loadaddr}" +# " BIN: tftpboot 0x200000 kernel.bin && go 0x200000" diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/csr.h b/ports/risc-v64/gnu/example_build/bananapi-f3/csr.h new file mode 100644 index 00000000..c5dfc630 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/csr.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This 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 + **************************************************************************/ + +/* RISC-V S-mode CSR helpers + * + * Privilege level: Supervisor (S-mode). + * Reference: RISC-V Privileged Specification + * + * Bit positions per the RISC-V Privileged Specification: + * + * sstatus: SIE(1) SPIE(5) SPP(8) FS(13:14) SUM(18) MXR(19) + * sie: SSIE(1) STIE(5) SEIE(9) + * scause: Interrupt bit = 63; Code 1=SSI, 5=STI, 9=SEI + */ + +#ifndef RISCV_CSR_H +#define RISCV_CSR_H + +#define SSTATUS_SIE (1L << 1) /* Supervisor Interrupt Enable */ +#define SSTATUS_SPIE (1L << 5) /* Previous SIE (saved on trap) */ +#define SSTATUS_SPP_MASK (1L << 8) +#define SSTATUS_SPP_S (1L << 8) /* SPP = Supervisor */ +#define SSTATUS_SPP_U (0L << 8) /* SPP = User */ +#define SSTATUS_FS (3L << 13) /* FP unit state (Off/Init/Clean/Dirty) */ + +#define SIE_SSIE (1L << 1) /* S-mode software interrupt */ +#define SIE_STIE (1L << 5) /* S-mode timer interrupt */ +#define SIE_SEIE (1L << 9) /* S-mode external interrupt */ + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/* + * Return the hart ID of the running core. + * + * mhartid is an M-mode CSR and cannot be read from S-mode. When booted + * from U-Boot only hart 0 is active (secondary harts remain parked in + * OpenSBI HSM), so we return 0. An SMP extension would need to pass + * the hart ID through a0 or shared memory at boot. + */ +static inline uint64_t riscv_get_core(void) +{ + return 0; +} + + +static inline uint64_t riscv_read_sstatus(void) +{ + uint64_t x; + asm volatile("csrr %0, sstatus" : "=r" (x)); + return x; +} + +static inline void riscv_write_sstatus(uint64_t x) +{ + asm volatile("csrw sstatus, %0" : : "r" (x)); +} + + +static inline void riscv_sintr_on(void) +{ + riscv_write_sstatus(riscv_read_sstatus() | SSTATUS_SIE); +} + +static inline void riscv_sintr_off(void) +{ + riscv_write_sstatus(riscv_read_sstatus() & ~SSTATUS_SIE); +} + +static inline int riscv_sintr_get(void) +{ + return (riscv_read_sstatus() & SSTATUS_SIE) != 0; +} + +static inline void riscv_sintr_restore(int enabled) +{ + if (enabled) + riscv_sintr_on(); + else + riscv_sintr_off(); +} + +/* Unified names used by BSP drivers (uart.c, etc.). */ +#define riscv_intr_on riscv_sintr_on +#define riscv_intr_off riscv_sintr_off +#define riscv_intr_get riscv_sintr_get +#define riscv_intr_restore riscv_sintr_restore + +#endif /* __ASSEMBLER__ */ +#endif /* RISCV_CSR_H */ diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/demo_threadx.c b/ports/risc-v64/gnu/example_build/bananapi-f3/demo_threadx.c new file mode 100644 index 00000000..2023df12 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/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/bananapi-f3/entry.S b/ports/risc-v64/gnu/example_build/bananapi-f3/entry.S new file mode 100644 index 00000000..f1d0f03b --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/entry.S @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This 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 + **************************************************************************/ + + .global _start + .extern main + .extern _sysstack_start + .extern _bss_start + .extern _bss_end + + .section .text.entry + .align 4 +_start: + /* Zero all general-purpose registers (x1–x31). */ + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + /* Set up the initial supervisor stack (16 KiB). */ + la t0, _sysstack_start + li t1, 0x4000 + add sp, t0, t1 + + /* Zero the .bss section. */ + la t0, _bss_start + la t1, _bss_end +_bss_clean_start: + bgeu t0, t1, _bss_clean_end + sb zero, 0(t0) + addi t0, t0, 1 + j _bss_clean_start +_bss_clean_end: + + call main + + /* Halt if main() ever returns. */ +_park: + wfi + j _park diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.c b/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.c new file mode 100644 index 00000000..4881ba3c --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.c @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "tx_port.h" +#include "csr.h" +#include "hwtimer.h" + +/* + * SBI legacy set_timer ecall + * + * EID (a7) = 0 (SBI_SET_TIMER) + * a0 = absolute mtime compare value + * + * Programs mtimecmp for the current hart and clears sip.STIP. + */ +static inline void sbi_set_timer(uint64_t stime_value) +{ + register uint64_t a0 asm("a0") = stime_value; + register uint64_t a7 asm("a7") = 0; /* SBI_SET_TIMER */ + asm volatile("ecall" + : "+r"(a0) + : "r"(a7) + : "memory"); +} + +/* + * Read the free-running mtime counter via the rdtime pseudo-instruction. + * Accessible from S-mode per RISC-V Priv Spec §10.1 (Zicntr extension). + */ +static inline uint64_t read_time(void) +{ + uint64_t t; + asm volatile("rdtime %0" : "=r"(t)); + return t; +} + +int hwtimer_init(void) +{ + uint64_t now = read_time(); + sbi_set_timer(now + TICKNUM_PER_TIMER); + return 0; +} + +int hwtimer_handler(void) +{ + uint64_t now = read_time(); + sbi_set_timer(now + TICKNUM_PER_TIMER); + return 0; +} diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.h b/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.h new file mode 100644 index 00000000..9265cee9 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/hwtimer.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef RISCV_HWTIMER_H +#define RISCV_HWTIMER_H + +#include <stdint.h> + +/* SpacemiT K1 TIMER (S-mode via SBI ecall) + * + * In S-mode the CLINT MMIO registers (mtime / mtimecmp) are protected + * by PMP and inaccessible. Timer operations are performed through the + * SBI legacy interface. + * + * rdtime - pseudo-instruction reading the time CSR (aliased to mtime + * by the implementation; accessible from S-mode per Priv + * Spec). + * + * SBI legacy set_timer (EID = 0, FID = 0) - programs mtimecmp on + * the current hart. Argument a0 = absolute compare value. + * Clears the pending supervisor timer interrupt (sip.STIP) + * as a side effect. + * + * + * Timebase frequency (DTS cpus { timebase-frequency = <0x16e3600>; }): + * 24,000,000 Hz (24 MHz). + * + * ThreadX tick rate: 10 Hz (100 ms period). + */ +#define TICKNUM_PER_SECOND 24000000UL +#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10) + +int hwtimer_init(void); +int hwtimer_handler(void); + +#endif /* RISCV_HWTIMER_H */ diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/link.lds b/ports/risc-v64/gnu/example_build/bananapi-f3/link.lds new file mode 100644 index 00000000..99d9ae49 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/link.lds @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (c) 2026 10xEngineers + * + * This 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 + **************************************************************************/ + +/* Memory Layout of the SpacemiT K1 SoC. + * + * Memory map: + * + * Physical Address Size Usage + * ────────────────── ────────── ────────────────────────────── + * 0x0000_0000 512 KiB Reserved - M-mode / OpenSBI + * 0x0008_0000 ~2 GiB Usable DRAM Bank 0 + * 0x0020_0000 - ← ThreadX kernel load address + * 0x7F00_0000 16 MiB Reserved - framebuffer / runtime + * 0x8000_0000–0xFFFF_FFFF PCI / MMIO hole (not DRAM) + * 0x1_0000_0000 ~14 GiB Usable DRAM Bank 1 + * + * Peripheral MMIO: + * + * 0xD401_7000 256 B UART0 (serial console) + * 0xE000_0000 64 MiB PLIC (interrupt controller) + * 0xE400_0000 64 KiB CLINT (timer / IPI) + * + * see more details on K1 Spec: + * Web : https://www.spacemit.com/community/document/?k1 + * PDF : https://cdn-resource.spacemit.com/file/chip/K1/K1_User_Manual_en.pdf + */ + + +OUTPUT_ARCH( "riscv" ) +ENTRY( _start ) + +PHDRS +{ + text PT_LOAD FLAGS(5); /* PF_R | PF_X */ + data PT_LOAD FLAGS(6); /* PF_R | PF_W */ +} + +SECTIONS +{ + . = 0x00200000; + + .text : { + KEEP(*(.text.entry)) + *(.text .text.*) + . = ALIGN(0x1000); + PROVIDE(etext = .); + } :text + + .rodata : { + . = ALIGN(16); + *(.srodata .srodata.*) + . = ALIGN(16); + *(.rodata .rodata.*) + } :text + + .data : { + . = ALIGN(16); + *(.sdata .sdata.*) + . = ALIGN(16); + *(.data .data.*) + } :data + + .bss : { + . = ALIGN(16); + _bss_start = .; + *(.sbss .sbss.*) + . = ALIGN(16); + *(.bss .bss.*) + _bss_end = .; + } :data + + .stack : { + . = ALIGN(4096); + _sysstack_start = .; + . += 0x4000; + _sysstack_end = .; + } :data + + PROVIDE(_end = .); +} diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/plic.c b/ports/risc-v64/gnu/example_build/bananapi-f3/plic.c new file mode 100644 index 00000000..6b04b65b --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/plic.c @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "plic.h" +#include <stddef.h> + +static irq_callback callbacks[MAX_CALLBACK_NUM]; + +#define PLIC_ENABLE(hart) PLIC_SENABLE(hart) +#define PLIC_PRIORITY_REG(hart) PLIC_SPRIORITY(hart) +#define PLIC_CLAIM_REG(hart) PLIC_SCLAIM(hart) +#define PLIC_COMPLETE_REG(hart) PLIC_SCOMPLETE(hart) + +void plic_irq_enable(int irqno) +{ + int hart = (int)riscv_get_core(); + uint32_t word = irqno / 32; + uint32_t bit = irqno % 32; + volatile uint32_t *en = (volatile uint32_t *)(PLIC_ENABLE(hart) + word * 4); + *en |= (1u << bit); +} + +void plic_irq_disable(int irqno) +{ + int hart = (int)riscv_get_core(); + uint32_t word = irqno / 32; + uint32_t bit = irqno % 32; + volatile uint32_t *en = (volatile uint32_t *)(PLIC_ENABLE(hart) + word * 4); + *en &= ~(1u << bit); +} + +void plic_prio_set(int irqno, int prio) +{ + PLIC_SET_PRIO(irqno, prio); +} + +int plic_prio_get(int irqno) +{ + return PLIC_GET_PRIO(irqno); +} + +int plic_register_callback(int irqno, irq_callback callback) +{ + if (!(irqno >= 0 && irqno < MAX_CALLBACK_NUM)) + return -1; + callbacks[irqno] = callback; + return 0; +} + +int plic_unregister_callback(int irqno) +{ + return plic_register_callback(irqno, NULL); +} + +int plic_init(void) +{ + int hart = (int)riscv_get_core(); + + for (int i = 0; i < MAX_CALLBACK_NUM; i++) + callbacks[i] = NULL; + + /* Mask everything for this hart. */ + for (int word = 0; word < (MAX_CALLBACK_NUM + 31) / 32; word++) + *(volatile uint32_t *)(PLIC_ENABLE(hart) + word * 4) = 0; + + /* Set hart threshold to 0 so any non-zero priority IRQ can fire. */ + *(volatile uint32_t *)PLIC_PRIORITY_REG(hart) = 0; + + /* + * Drain stale pending interrupts left over from a prior boot stage + * (BootROM / OpenSBI / U-Boot). We temporarily enable every source + * so claim returns the actual highest-priority pending ID, then + * complete whatever was claimed. Loop until claim returns 0 + * (no more pending). This follows the PLIC spec: claim returns 0 + * when nothing is pending for this context. + */ + for (int word = 0; word < (PLIC_NUM_SOURCES + 31) / 32; word++) + *(volatile uint32_t *)(PLIC_ENABLE(hart) + word * 4) = 0xFFFFFFFFu; + + for (;;) { + uint32_t id = *(volatile uint32_t *)PLIC_CLAIM_REG(hart); + if (id == 0) + break; + *(volatile uint32_t *)PLIC_COMPLETE_REG(hart) = id; + } + + /* Re-mask everything; individual drivers will enable their sources. */ + for (int word = 0; word < (PLIC_NUM_SOURCES + 31) / 32; word++) + *(volatile uint32_t *)(PLIC_ENABLE(hart) + word * 4) = 0; + + /* + * Set default priority for every source to PLIC_DEFAULT_PRIORITY (2), + * Priority 0 means "never pending" per the SiFive PLIC spec, so any + * source that should be active must have priority >= 1. Individual + * drivers may override this with plic_prio_set() later. + */ + for (int i = 1; i <= PLIC_NUM_SOURCES; i++) + PLIC_SET_PRIO(i, PLIC_DEFAULT_PRIORITY); + + return 0; +} + +int plic_claim(void) +{ + int hart = (int)riscv_get_core(); + return (int)*(volatile uint32_t *)PLIC_CLAIM_REG(hart); +} + +void plic_complete(int irqno) +{ + int hart = (int)riscv_get_core(); + *(volatile uint32_t *)PLIC_COMPLETE_REG(hart) = (uint32_t)irqno; +} + +int plic_irq_intr(void) +{ + int ret = -1; + int irqno = plic_claim(); + if (irqno == 0) + return ret; + if (irqno < MAX_CALLBACK_NUM && callbacks[irqno] != NULL) + ret = (callbacks[irqno])(irqno); + plic_complete(irqno); + return ret; +} diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/plic.h b/ports/risc-v64/gnu/example_build/bananapi-f3/plic.h new file mode 100644 index 00000000..fa755f89 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/plic.h @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef RISCV_PLIC_H +#define RISCV_PLIC_H + +#include "csr.h" +#include <stdint.h> + +/* + * SpacemiT K1 PLIC - SiFive-compatible Platform-Level Interrupt Controller. + * + * From bananapi-f3.dts (linux main tree): + * interrupt-controller@e0000000 { + * reg-names = "control"; + * interrupts-extended = <0x10 0x0b 0x10 0x09 0x11 0x0b 0x11 0x09 0x12 0x0b 0x12 0x09 0x13 0x0b 0x13 0x09 0x14 0x0b 0x14 0x09 0x15 0x0b 0x15 0x09 0x16 0x0b 0x16 0x09 0x17 0x0b 0x17 0x09>; + * compatible = "riscv,plic0"; + * #interrupt-cells = <0x01>; + * reg = <0x00 0xe0000000 0x00 0x4000000>; + * phandle = <0x1e>; + * riscv,ndev = <0x9f>; // (159 external interrupt sources) + * riscv,max-priority = <0x07>; // (priority levels 1..7; 0 = disabled) + * interrupt-controller; + * }; + + * The RISCV_APB block is at 0xE000_0000 with size 0x1000_0000. + * Within that block the PLIC occupies 0xE000_0000..0xE3FF_FFFF + * (64 MiB) and the CLINT lives at 0xE400_0000. + * + * The K1 main CPU has up to 8 X60 cores (harts 0..7). Each hart + * exposes both an M-mode and S-mode interrupt context to the PLIC. + * + * PLIC register layout: + * + * Offset Size Description + * ────────────── ────── ──────────────────────────────────────────── + * 0x000000 4/src Source priority (src 0 reserved, 1..159) + * 0x001000 20B Pending bits (5 × 32-bit words) + * 0x002000 0x100/h Enable bits per hart (M-mode at ctx 0) + * 0x002080 0x100/h Enable bits per hart (S-mode at ctx 1) + * 0x200000 0x2000/h Threshold + Claim/Complete (M-mode ctx 0) + * 0x201000 0x2000/h Threshold + Claim/Complete (S-mode ctx 1) + * + * Context mapping: + * EN_PER_HART = 0x100 (two contexts × 0x80 each) + * EN_PER_CONTEXT = 0x80 + * THRES_PER_HART = 0x2000 (two contexts × 0x1000 each) + * THRES_PER_CTX = 0x1000 + * THRES_CLAIM_OFF = 0x4 (claim/complete at threshold + 4) + * + */ + +#define PLIC 0xE0000000UL +#define PLIC_SIZE 0x04000000UL /* 64 MiB, from DTS reg */ + +#define PLIC_PRIORITY (PLIC + 0x0) +#define PLIC_PRIO_PER_ID 4 /* stride: 4 bytes/source */ + +#define PLIC_EN (PLIC + 0x2000) +#define PLIC_EN_PER_HART 0x100 +#define PLIC_EN_PER_CONTEXT 0x80 + + +#define PLIC_SENABLE(hart) (PLIC_EN + (hart) * PLIC_EN_PER_HART + PLIC_EN_PER_CONTEXT) + +#define PLIC_THRES (PLIC + 0x200000) +#define PLIC_THRES_PER_HART 0x2000 +#define PLIC_THRES_PER_CONTEXT 0x1000 +#define PLIC_THRES_CLAIM_OFF 0x4 + +/* + * S-mode threshold/claim = M-mode base + one context offset (0x1000). + */ +#define PLIC_SPRIORITY(hart) (PLIC_THRES + (hart) * PLIC_THRES_PER_HART + PLIC_THRES_PER_CONTEXT) +#define PLIC_SCLAIM(hart) (PLIC_SPRIORITY(hart) + PLIC_THRES_CLAIM_OFF) +#define PLIC_SCOMPLETE(hart) PLIC_SCLAIM(hart) + +#define PLIC_GET_PRIO(irqno) (*(volatile uint32_t *)(PLIC_PRIORITY + (irqno) * PLIC_PRIO_PER_ID)) +#define PLIC_SET_PRIO(irqno, prio) (*(volatile uint32_t *)(PLIC_PRIORITY + (irqno) * PLIC_PRIO_PER_ID) = (prio)) + + +#define PLIC_NUM_SOURCES 159 +#define PLIC_MAX_PRIORITY 7 +#define PLIC_DEFAULT_PRIORITY 2 +#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_prio_get(int irqno); +void plic_prio_set(int irqno, int prio); +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/bananapi-f3/trap.c b/ports/risc-v64/gnu/example_build/bananapi-f3/trap.c new file mode 100644 index 00000000..6418b02c --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/trap.c @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This 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 + **************************************************************************/ + +/* + * S-mode trap handler + */ + +#include "csr.h" +#include "uart.h" +#include "hwtimer.h" +#include "plic.h" +#include <stdint.h> +#include <tx_port.h> +#include <tx_api.h> + +/* scause bit 63: interrupt flag. */ +#define SCAUSE_INTERRUPT 0x8000000000000000ull + +#define SCAUSE_S_TIMER_INT (SCAUSE_INTERRUPT | 5u) +#define SCAUSE_S_EXTERNAL_INT (SCAUSE_INTERRUPT | 9u) + +extern void _tx_timer_interrupt(void); + +void trap_handler(uintptr_t cause, uintptr_t epc, uintptr_t tval) +{ + (void)epc; + (void)tval; + + if (cause & SCAUSE_INTERRUPT) + { + if (cause == SCAUSE_S_TIMER_INT) + { + hwtimer_handler(); + _tx_timer_interrupt(); + } + else if (cause == SCAUSE_S_EXTERNAL_INT) + { + if (plic_irq_intr() != 0) + { + puts("[trap] PLIC dispatch failed"); + while (1) + ; + } + } + else + { + puts("[trap] unhandled S-mode interrupt"); + while (1) + ; + } + } + else + { + puts("[trap] unhandled synchronous exception"); + while (1) + ; + } +} diff --git a/ports/risc-v32/clang/src/tx_initialize_low_level.S b/ports/risc-v64/gnu/example_build/bananapi-f3/tx_initialize_low_level.S index 467c3735..3cfa83c3 100644 --- a/ports/risc-v32/clang/src/tx_initialize_low_level.S +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/tx_initialize_low_level.S @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2026 Quintauris + * Copyright (c) 2025 10xEngineers * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -8,40 +8,25 @@ * SPDX-License-Identifier: MIT **************************************************************************/ - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** ThreadX Component */ -/** */ -/** Initialize */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - .section .data - .global __tx_free_memory_start -__tx_free_memory_start: - +#include "csr.h" .section .text + .align 4 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_initialize_low_level RISC-V32/GNU */ -/* 6.4.x */ +/* trap_entry RISC-V64/GNU */ +/* 6.2.1 */ /* AUTHOR */ /* */ -/* Francisco Merino, Quintauris */ +/* Akif Ejaz, 10xEngineers */ /* */ /* 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. */ +/* This function is responsible for riscv processor trap handle */ +/* It will do the contex save and call c trap_handler and do contex */ +/* load */ /* */ /* INPUT */ /* */ @@ -53,60 +38,102 @@ __tx_free_memory_start: /* */ /* CALLS */ /* */ -/* None */ +/* trap_handler */ /* */ /* CALLED BY */ /* */ -/* _tx_initialize_kernel_enter ThreadX entry function */ +/* hardware exception */ /* */ /**************************************************************************/ -/* VOID _tx_initialize_low_level(VOID) -{ */ -// .global _tx_initialize_low_level - .weak _tx_initialize_low_level -_tx_initialize_low_level: - /* Save the system stack pointer. */ - /* _tx_thread_system_stack_ptr = sp; */ + .global trap_entry + .extern trap_handler + .extern _tx_thread_context_save + .extern _tx_thread_context_restore - la t0, _tx_thread_system_stack_ptr // Pickup address of system stack ptr - sw sp, 0(t0) // Save system stack pointer +trap_entry: +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi sp, sp, -520 /* 65 * 8: integer + FP */ +#else + addi sp, sp, -256 /* 32 * 8: integer only */ +#endif - /* Pickup first free address. */ - /* _tx_initialize_unused_memory(__tx_free_memory_start); */ + sd x1, 224(sp) /* Save RA at offset 28*8 */ - la t0, __tx_free_memory_start // Pickup first free address - la t1, _tx_initialize_unused_memory // Pickup address of unused memory - sw t0, 0(t1) // Save unused memory address + call _tx_thread_context_save - /* Initialize floating point control/status register if floating point is enabled. */ -#ifdef __riscv_flen - li t0, 0 - csrw fcsr, t0 // Clear FP control/status register -#endif + csrr a0, scause + csrr a1, sepc + csrr a2, stval + addi sp, sp, -8 + sd ra, 0(sp) + call trap_handler + ld ra, 0(sp) + addi sp, sp, 8 - ret + call _tx_thread_context_restore + /* never returns */ +_trap_err: + wfi + j _trap_err + + .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. */ +/* */ +/**************************************************************************/ + + .global _tx_initialize_low_level + .weak _tx_initialize_low_level + .extern _end + .extern board_init + .extern trap_entry + .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 */ -/* Timer Interrupt Handler Note: - Platform-specific implementations must provide their own timer ISR. - The timer interrupt handler should follow this execution flow: + la t0, _end + la t1, _tx_initialize_unused_memory + sd t0, 0(t1) /* First free address */ - 1. Disable interrupts (if not done by hardware exception entry) - 2. Allocate interrupt stack frame (65*4 bytes with FP, 32*4 bytes without) - 3. Save RA (x1) on the stack at offset 28*4 - 4. Call _tx_thread_context_save to save thread context - 5. Call _tx_timer_interrupt to process the timer tick - 6. Call _tx_thread_context_restore to resume execution (does not return) + /* Disable global S-mode interrupts during early init. */ + li t0, SSTATUS_SIE + csrrc zero, sstatus, t0 - Example (for CLINT timer): + /* Set SPIE = 1 so SRET re-enables interrupts. */ + li t0, SSTATUS_SPIE + csrrs zero, sstatus, t0 - _tx_timer_interrupt_handler: - addi sp, sp, -32*4 - sw ra, 28*4(sp) - call _tx_thread_context_save - call _tx_timer_interrupt - j _tx_thread_context_restore + /* Enable S-mode timer and external interrupts. */ + li t0, (SIE_STIE | SIE_SEIE) + csrrs zero, sie, t0 - The port assumes Machine mode (M-mode) execution. - For Supervisor mode (S-mode), use sstatus and SIE/SPIE instead of mstatus. - See the RISC-V Privileged Specification for more details. */
\ No newline at end of file +#ifdef __riscv_flen + li t0, SSTATUS_FS + csrrs zero, sstatus, t0 + fscsr x0 +#endif + + addi sp, sp, -8 + sd ra, 0(sp) + call board_init + ld ra, 0(sp) + addi sp, sp, 8 + + la t0, trap_entry + csrw stvec, t0 + ret diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/uart.c b/ports/risc-v64/gnu/example_build/bananapi-f3/uart.c new file mode 100644 index 00000000..3ef89d09 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/uart.c @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#include "uart.h" +#include "csr.h" +#include "plic.h" +#include <stdint.h> + +/* + * The K1 UART Register layout + * + * Offset Name Access Description + * ────── ────── ────── ────────────────────────────── + * 0x00 RBR/THR R/W Receive Buffer / Transmit Hold + * 0x00 DLL R/W (DLAB=1) Divisor Latch Low + * 0x04 IER R/W Interrupt Enable + * 0x04 DLH R/W (DLAB=1) Divisor Latch High + * 0x08 IIR R Interrupt Identification + * 0x08 FCR W FIFO Control + * 0x0C LCR R/W Line Control + * 0x10 MCR R/W Modem Control + * 0x14 LSR R Line Status + * 0x18 MSR R Modem Status + * 0x1C SPR R/W Scratchpad + */ + +#define REG(off) (*(volatile uint32_t *)(UART0 + (off))) + +#define RHR 0x00 +#define THR 0x00 +#define DLL 0x00 +#define IER 0x04 +#define DLH 0x04 +#define IIR 0x08 +#define FCR 0x08 +#define LCR 0x0C +#define MCR 0x10 +#define LSR 0x14 + + +#define IER_RAVIE (1u << 0) /* Receiver data available IRQ enable */ +#define IER_TIE (1u << 1) /* Transmit data request IRQ enable */ +#define IER_RLSE (1u << 2) /* Receiver line status IRQ enable */ +#define IER_UUE (1u << 6) /* UART unit enable */ + +#define FCR_TRFIFOE (1u << 0) /* Transmit/Receive FIFO enable */ +#define FCR_RESETRF (1u << 1) /* Reset receive FIFO */ +#define FCR_RESETTF (1u << 2) /* Reset transmit FIFO */ +#define FCR_FIFO_CLEAR (FCR_RESETRF | FCR_RESETTF) + +#define LCR_WLS_8 (3u << 0) /* 8-bit word */ +#define LCR_DLAB (1u << 7) /* Divisor latch access bit */ + +#define LSR_DR (1u << 0) /* Data ready in receive FIFO */ +#define LSR_TDRQ (1u << 5) /* Transmit holding/FIFO ready */ +#define LSR_TEMT (1u << 6) /* Transmitter empty */ + +#define ReadReg(off) (REG(off) & 0xFF) +#define WriteReg(off, v) (REG(off) = (uint32_t)((v) & 0xFF)) + +int uart_init(void) +{ + /* + * If a prior boot stage (BootROM / OpenSBI / U-Boot) already + * configured the UART, keep its baud-rate divisor so we keep + * a working console. Just make sure interrupts are masked, + * the FIFOs are clean and the unit-enable bit is set. + */ + WriteReg(IER, 0x00); + + /* + * Program the baud-rate divisor for 115200 baud. + * The PXA UART functional clock on K1 is 14.7456 MHz: + * 14,745,600 / (16 × 8) = 115,200 baud → DLL = 8, DLH = 0. + */ + WriteReg(LCR, LCR_DLAB); + WriteReg(DLL, 0x08); + WriteReg(DLH, 0x00); + + WriteReg(LCR, LCR_WLS_8); + WriteReg(FCR, FCR_TRFIFOE | FCR_FIFO_CLEAR); + + /* Enable the UART transmit/receive engines (K1-specific). */ + WriteReg(IER, IER_UUE); + + plic_irq_enable(UART0_IRQ); + plic_prio_set(UART0_IRQ, 1); + + puts("[uart] UART0 initialized"); + return 0; +} + +static inline void uart_putc_nolock(int ch) +{ + while ((ReadReg(LSR) & LSR_TDRQ) == 0) + ; + WriteReg(THR, ch); +} + +int uart_putc(int ch) +{ + int intr_enable = riscv_intr_get(); + riscv_intr_off(); + uart_putc_nolock(ch); + riscv_intr_restore(intr_enable); + return 1; +} + +int uart_puts(const char *str) +{ + int i; + int intr_enable = riscv_intr_get(); + riscv_intr_off(); + for (i = 0; str[i] != 0; i++) + uart_putc_nolock(str[i]); + uart_putc_nolock('\r'); + uart_putc_nolock('\n'); + riscv_intr_restore(intr_enable); + return i; +} diff --git a/ports/risc-v64/gnu/example_build/bananapi-f3/uart.h b/ports/risc-v64/gnu/example_build/bananapi-f3/uart.h new file mode 100644 index 00000000..b03d0dd4 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/bananapi-f3/uart.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (c) 2025 10xEngineers + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * SPDX-License-Identifier: MIT + **************************************************************************/ + +#ifndef RISCV_UART_H +#define RISCV_UART_H + +/* SpacemiT K1 UART0 + * + * DTS node: /soc/serial@d4017000 + * serial@d4017000 { + * power-domains = <0x20 0x00>; + * reg-io-width = <0x04>; + * clk-fpga = <0xe11130>; + * pinctrl-names = "default"; + * interconnect-names = "dma-mem"; + * pinctrl-0 = <0x23>; + * interconnects = <0x22>; + * resets = <0x1d 0x01>; + * interrupts = <0x2a>; + * clocks = <0x03 0x3a 0x03 0xb4>; + * interrupt-parent = <0x1e>; + * dma-names = "rx", "tx"; + * cpuidle,pm-runtime,sleep; + * compatible = "spacemit,pxa-uart"; + * status = "okay"; + * reg = <0x00 0xd4017000 0x00 0x100>; + * dmas = <0x21 0x04 0x01 0x21 0x03 0x01>; + * reg-shift = <0x02>; + * }; + + + * K1 User Manual Section 16.3.4 defines the register layout. Because + * reg-shift = 2, the logical 16550A register indices (0..7) map to + * byte offsets 0x00, 0x04, 0x08, ..., 0x1C (stride of 4). + * + * Register map (at UART0 + offset): + * + * Offset Name R/W Description + * ────── ────────── ─── ──────────────────────────────────── + * 0x00 RBR/THR/DLL R/W Receive Buffer / Transmit Holding / + * Divisor Latch Low (when LCR.DLAB=1) + * 0x04 IER/DLH R/W Interrupt Enable / + * Divisor Latch High (when LCR.DLAB=1) + * 0x08 IIR/FCR R/W Interrupt Identification (R) / + * FIFO Control (W) + * 0x0C LCR R/W Line Control + * 0x10 MCR R/W Modem Control + * 0x14 LSR R Line Status + * 0x18 MSR R Modem Status + * 0x1C SPR R/W Scratchpad + * + */ + +#define UART0 0xD4017000UL +#define UART0_SIZE 0x100UL /* 256 bytes, from DTS reg */ +#define UART0_IRQ 42 /* DTS: interrupts = <0x2a> */ +#define UART0_REG_SHIFT 2 /* DTS: reg-shift = <0x02> */ + +#define puts uart_puts + +int uart_init(void); +int uart_putc(int ch); +int uart_puts(const char *str); + +#endif /* RISCV_UART_H */ 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 60a61163..805a1ac8 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/board.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/board.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + #include "plic.h" #include "hwtimer.h" #include "uart.h" diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh b/ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh index 24a4c3ac..0568e7a8 100755 --- a/ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh +++ b/ports/risc-v64/gnu/example_build/qemu_virt/build_libthreadx.sh @@ -1,6 +1,35 @@ #!/bin/bash +############################################################################## +# 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 +############################################################################## + +printf "y\n" | rm -rf ../../../../../build/ +rm -f kernel.elf pushd ../../../../../ cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake . cmake --build ./build/ popd + +riscv64-unknown-elf-gcc \ + -march=rv64gc -mabi=lp64d \ + -mcmodel=medany -O0 -g3 -Wall \ + -ffunction-sections -fdata-sections \ + -I../../../../../common/inc \ + -I../../inc \ + entry.S \ + tx_initialize_low_level.S \ + board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \ + -L../../../../../build -lthreadx \ + -T link.lds -nostartfiles \ + -o kernel.elf + + +qemu-system-riscv64 -nographic -smp 1 -bios none -m 128M -machine virt -kernel kernel.elf diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/csr.h b/ports/risc-v64/gnu/example_build/qemu_virt/csr.h index 92ca6644..b5df6f12 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/csr.h +++ b/ports/risc-v64/gnu/example_build/qemu_virt/csr.h @@ -1,374 +1 @@ -/*************************************************************************** - * 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 - **************************************************************************/ - - -#ifndef RISCV_CSR_H -#define RISCV_CSR_H - - -// Machine Status Register, mstatus -#define MSTATUS_MPP_MASK (3L << 11) // previous mode. -#define MSTATUS_MPP_M (3L << 11) -#define MSTATUS_MPP_S (1L << 11) -#define MSTATUS_MPP_U (0L << 11) -#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable. -#define MSTATUS_MPIE (1L << 7) -#define MSTATUS_FS (1L << 13) - -// Machine-mode Interrupt Enable -#define MIE_MTIE (1L << 7) -#define MIE_MSIE (1L << 3) -#define MIE_MEIE (1L << 11) -#define MIE_STIE (1L << 5) // supervisor timer -#define MIE_SSIE (1L << 1) -#define MIE_SEIE (1L << 9) - -// Supervisor Status Register, sstatus -#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User -#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable -#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable -#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable -#define SSTATUS_UIE (1L << 0) // User Interrupt Enable -#define SSTATUS_SPIE (1L << 5) -#define SSTATUS_UPIE (1L << 4) - -// Supervisor Interrupt Enable -#define SIE_SEIE (1L << 9) // external -#define SIE_STIE (1L << 5) // timer -#define SIE_SSIE (1L << 1) // software - -#ifndef __ASSEMBLER__ - -#include <stdint.h> - -static inline uint64_t riscv_get_core() -{ - uint64_t x; - asm volatile("csrr %0, mhartid" : "=r" (x) ); - return x; -} - -static inline uint64_t riscv_get_mstatus() -{ - uint64_t x; - asm volatile("csrr %0, mstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mstatus(uint64_t x) -{ - asm volatile("csrw mstatus, %0" : : "r" (x)); -} - -// machine exception program counter, holds the -// instruction address to which a return from -// exception will go. -static inline void riscv_writ_mepc(uint64_t x) -{ - asm volatile("csrw mepc, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_sstatus() -{ - uint64_t x; - asm volatile("csrr %0, sstatus" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sstatus(uint64_t x) -{ - asm volatile("csrw sstatus, %0" : : "r" (x)); -} - -// Supervisor Interrupt Pending -static inline uint64_t riscv_get_sip() -{ - uint64_t x; - asm volatile("csrr %0, sip" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sip(uint64_t x) -{ - asm volatile("csrw sip, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_sie() -{ - uint64_t x; - asm volatile("csrr %0, sie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_sie(uint64_t x) -{ - asm volatile("csrw sie, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_mie() -{ - uint64_t x; - asm volatile("csrr %0, mie" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mie(uint64_t x) -{ - asm volatile("csrw mie, %0" : : "r" (x)); -} - -// supervisor exception program counter, holds the -// instruction address to which a return from -// exception will go. -static inline void riscv_writ_sepc(uint64_t x) -{ - asm volatile("csrw sepc, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_sepc() -{ - uint64_t x; - asm volatile("csrr %0, sepc" : "=r" (x) ); - return x; -} - -// Machine Exception Delegation -static inline uint64_t riscv_get_medeleg() -{ - uint64_t x; - asm volatile("csrr %0, medeleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_medeleg(uint64_t x) -{ - asm volatile("csrw medeleg, %0" : : "r" (x)); -} - -// Machine Interrupt Delegation -static inline uint64_t riscv_get_mideleg() -{ - uint64_t x; - asm volatile("csrr %0, mideleg" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_mideleg(uint64_t x) -{ - asm volatile("csrw mideleg, %0" : : "r" (x)); -} - -// Supervisor Trap-Vector Base Address -// low two bits are mode. -static inline void riscv_writ_stvec(uint64_t x) -{ - asm volatile("csrw stvec, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_stvec() -{ - uint64_t x; - asm volatile("csrr %0, stvec" : "=r" (x) ); - return x; -} - -// Supervisor Timer Comparison Register -static inline uint64_t riscv_get_stimecmp() -{ - uint64_t x; - // asm volatile("csrr %0, stimecmp" : "=r" (x) ); - asm volatile("csrr %0, 0x14d" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_stimecmp(uint64_t x) -{ - // asm volatile("csrw stimecmp, %0" : : "r" (x)); - asm volatile("csrw 0x14d, %0" : : "r" (x)); -} - -// Machine Environment Configuration Register -static inline uint64_t riscv_get_menvcfg() -{ - uint64_t x; - // asm volatile("csrr %0, menvcfg" : "=r" (x) ); - asm volatile("csrr %0, 0x30a" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_menvcfg(uint64_t x) -{ - // asm volatile("csrw menvcfg, %0" : : "r" (x)); - asm volatile("csrw 0x30a, %0" : : "r" (x)); -} - -// Physical Memory Protection -static inline void riscv_writ_pmpcfg0(uint64_t x) -{ - asm volatile("csrw pmpcfg0, %0" : : "r" (x)); -} - -static inline void riscv_writ_pmpaddr0(uint64_t x) -{ - asm volatile("csrw pmpaddr0, %0" : : "r" (x)); -} - -// supervisor address translation and protection; -// holds the address of the page table. -static inline void riscv_writ_satp(uint64_t x) -{ - asm volatile("csrw satp, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_satp() -{ - uint64_t x; - asm volatile("csrr %0, satp" : "=r" (x) ); - return x; -} - -// Supervisor Trap Cause -static inline uint64_t riscv_get_scause() -{ - uint64_t x; - asm volatile("csrr %0, scause" : "=r" (x) ); - return x; -} - -// Supervisor Trap Value -static inline uint64_t riscv_get_stval() -{ - uint64_t x; - asm volatile("csrr %0, stval" : "=r" (x) ); - return x; -} - -// Machine-mode Counter-Enable -static inline void riscv_writ_mcounteren(uint64_t x) -{ - asm volatile("csrw mcounteren, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_mcounteren() -{ - uint64_t x; - asm volatile("csrr %0, mcounteren" : "=r" (x) ); - return x; -} - -// machine-mode cycle counter -static inline uint64_t riscv_get_time() -{ - uint64_t x; - asm volatile("csrr %0, time" : "=r" (x) ); - return x; -} - -// enable device interrupts -static inline void riscv_sintr_on() -{ - uint64_t sstatus = riscv_get_sstatus(); - sstatus |= SSTATUS_SIE; - riscv_writ_sstatus(sstatus); -} - -// disable device interrupts -static inline void riscv_sintr_off() -{ - uint64_t sstatus = riscv_get_sstatus(); - sstatus &= (~SSTATUS_SIE); - riscv_writ_sstatus(sstatus); -} - -// are device interrupts enabled? -static inline int riscv_sintr_get() -{ - uint64_t x = riscv_get_sstatus(); - return (x & SSTATUS_SIE) != 0; -} - -static inline void riscv_sintr_restore(int x) -{ - if(x) - riscv_sintr_on(); - else - riscv_sintr_off(); -} - -// enable device interrupts -static inline void riscv_mintr_on() -{ - uint64_t mstatus = riscv_get_mstatus(); - mstatus |= MSTATUS_MIE; - riscv_writ_mstatus(mstatus); -} - -// disable device interrupts -static inline void riscv_mintr_off() -{ - uint64_t mstatus = riscv_get_mstatus(); - mstatus &= (~MSTATUS_MIE); - riscv_writ_mstatus(mstatus); -} - -// are device interrupts enabled? -static inline int riscv_mintr_get() -{ - uint64_t x = riscv_get_mstatus(); - return (x & MSTATUS_MIE) != 0; -} - -static inline void riscv_mintr_restore(int x) -{ - if(x) - riscv_mintr_on(); - else - riscv_mintr_off(); -} - -static inline uint64_t riscv_get_sp() -{ - uint64_t x; - asm volatile("mv %0, sp" : "=r" (x) ); - return x; -} - -// read and write tp, the thread pointer, which xv6 uses to hold -// this core's hartid (core number), the index into cpus[]. -static inline uint64_t riscv_get_tp() -{ - uint64_t x; - asm volatile("mv %0, tp" : "=r" (x) ); - return x; -} - -static inline void riscv_writ_tp(uint64_t x) -{ - asm volatile("mv tp, %0" : : "r" (x)); -} - -static inline uint64_t riscv_get_ra() -{ - uint64_t x; - asm volatile("mv %0, ra" : "=r" (x) ); - return x; -} - -// flush the TLB. -static inline void sfence_vma() -{ - // the zero, zero means flush all TLB entries. - asm volatile("sfence.vma zero, zero"); -} - -#endif // __ASSEMBLER__ - -#endif +../../../../risc-v_common/inc/csr.h
\ No newline at end of file diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c b/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c index 229dcc68..d3195019 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c @@ -1,11 +1,27 @@ +/***************************************************************************/ +/* 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" +#if defined(__riscv_vector) +#define DEMO_STACK_SIZE (1024 + 16448) /* 16448 for RVV Extension */ +#define DEMO_BYTE_POOL_SIZE (9180 + 148032) /* 148032 for RVV Extension */ +#else #define DEMO_STACK_SIZE 1024 #define DEMO_BYTE_POOL_SIZE 9180 +#endif #define DEMO_BLOCK_POOL_SIZE 100 #define DEMO_QUEUE_SIZE 100 diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/entry.S b/ports/risc-v64/gnu/example_build/qemu_virt/entry.S new file mode 100644 index 00000000..2b68310d --- /dev/null +++ b/ports/risc-v64/gnu/example_build/qemu_virt/entry.S @@ -0,0 +1,73 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + + +.section .text +.align 4 +.global _start +.extern main +.extern _sysstack_start +.extern _bss_start +.extern _bss_end +_start: + csrr t0, mhartid + bne t0, zero, 1f + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + la t0, _sysstack_start +#ifdef __riscv_vector + li t1, 0x5000 +#else + li t1, 0x1000 +#endif + add sp, t0, t1 + la t0, _bss_start + la t1, _bss_end +_bss_clean_start: + bgeu t0, t1, _bss_clean_end + sb zero, 0(t0) + addi t0, t0, 1 + j _bss_clean_start +_bss_clean_end: + call main +1: + /* todo smp */ + wfi + j 1b diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/entry.s b/ports/risc-v64/gnu/example_build/qemu_virt/entry.s deleted file mode 100644 index 9b202ca1..00000000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/entry.s +++ /dev/null @@ -1,58 +0,0 @@ - -.section .text -.align 4 -.global _start -.extern main -.extern _sysstack_start -.extern _bss_start -.extern _bss_end -_start: - csrr t0, mhartid - bne t0, zero, 1f - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10, 0 - li x11, 0 - li x12, 0 - li x13, 0 - li x14, 0 - li x15, 0 - li x16, 0 - li x17, 0 - li x18, 0 - li x19, 0 - li x20, 0 - li x21, 0 - li x22, 0 - li x23, 0 - li x24, 0 - li x25, 0 - li x26, 0 - li x27, 0 - li x28, 0 - li x29, 0 - li x30, 0 - li x31, 0 - la t0, _sysstack_start - li t1, 0x1000 - add sp, t0, t1 - la t0, _bss_start - la t1, _bss_end -_bss_clean_start: - bgeu t0, t1, _bss_clean_end - sb zero, 0(t0) - addi t0, t0, 1 - j _bss_clean_start -_bss_clean_end: - call main -1: - /* todo smp */ - wfi - j 1b diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c b/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c index 29cf1117..122e71a1 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + #include "tx_port.h" #include "csr.h" #include "hwtimer.h" 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 522f90d9..d0d8a6bc 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/link.lds +++ b/ports/risc-v64/gnu/example_build/qemu_virt/link.lds @@ -42,6 +42,9 @@ SECTIONS . = ALIGN(4096); _sysstack_start = .; . += 0x1000; +#ifdef __riscv_vector + . += 0x4000; +#endif _sysstack_end = .; } diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/plic.c b/ports/risc-v64/gnu/example_build/qemu_virt/plic.c index 01e5c71a..b247f4fe 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/plic.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/plic.c @@ -1,72 +1 @@ -#include "plic.h" -#include <stddef.h> -irq_callback callbacks[MAX_CALLBACK_NUM]; - -void plic_irq_enable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno)); - return; -} - -void plic_irq_disable(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno))); - return; -} - -void plic_prio_set(int irqno, int prio) -{ - PLIC_SET_PRIO(irqno, prio); -} - -int plic_prio_get(int irqno) -{ - return PLIC_GET_PRIO(irqno); -} - -int plic_register_callback(int irqno, irq_callback callback) -{ - if(!(irqno >=0 && irqno < MAX_CALLBACK_NUM)) - return -1; - callbacks[irqno] = callback; - return 0; -} - -int plic_unregister_callback(int irqno) -{ - return plic_register_callback(irqno, NULL); -} - -int plic_init(void) -{ - for(int i=0;i<MAX_CALLBACK_NUM;i++) - { - callbacks[i] = NULL; - } - return 0; -} - -int plic_claim(void) -{ - int hart = riscv_get_core(); - return (*(uint32_t*)PLIC_MCLAIM(hart)); -} - -void plic_complete(int irqno) -{ - int hart = riscv_get_core(); - *(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; - return; -} - -int plic_irq_intr(void) -{ - int ret = -1; - int irqno = plic_claim(); - if(callbacks[irqno] != NULL) - ret = (callbacks[irqno])(irqno); - plic_complete(irqno); - return ret; -} +../../../../risc-v_common/example_build/plic/plic.c
\ No newline at end of file diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/plic.h b/ports/risc-v64/gnu/example_build/qemu_virt/plic.h index 42e4c925..f776a3d2 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/plic.h +++ b/ports/risc-v64/gnu/example_build/qemu_virt/plic.h @@ -1,51 +1 @@ -/*************************************************************************** - * 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 - **************************************************************************/ - - -#ifndef RISCV_PLIC_H -#define RISCV_PLIC_H - -#include "csr.h" -#include <stdint.h> - -#define PLIC 0x0c000000L -#define PLIC_PRIORITY (PLIC + 0x0) -#define PLIC_PENDING (PLIC + 0x1000) -#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100) -#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100) -#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000) -#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000) -#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000) -#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000) -#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 MAX_CALLBACK_NUM 128 -typedef int (*irq_callback)(int irqno); - -void plic_irq_enable(int irqno); -void plic_irq_disable(int irqno); -int plic_prio_get(int irqno); -void plic_prio_set(int irqno, int prio); -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 - +../../../../risc-v_common/example_build/plic/plic.h
\ No newline at end of file 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 new file mode 100644 index 00000000..861f50e6 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py @@ -0,0 +1,286 @@ +############################################################################## +# 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 +############################################################################## + +import subprocess +import sys +import os +import argparse +import socket +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 + +def get_free_port(): + """Finds a free 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. + """ + print(f"Testing ELF: {elf_path}") + print(f"QEMU: {qemu_bin}") + print(f"GDB: {gdb_bin}") + + # Find a free port for GDB connection + gdb_port = get_free_port() + print(f"Using GDB port: {gdb_port}") + + # 1. Start QEMU in the background + qemu_cmd = [ + qemu_bin, + "-M", "virt", + "-nographic", + "-bios", "none", # Disable default OpenSBI + "-kernel", elf_path, + "-gdb", f"tcp::{gdb_port}", "-S", + "-monitor", "none", # Disable monitor + "-serial", "stdio" # Redirect serial output to stdio + ] + + print(f"Starting QEMU: {' '.join(qemu_cmd)}") + qemu_process = subprocess.Popen( + qemu_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + if qemu_process.poll() is not None: + print("QEMU failed to start.") + print(qemu_process.stderr.read()) + return False + + # 2. Create a GDB command file + gdb_cmds = """ +file {elf} +target remote :{port} +set pagination off +set confirm off + +# Setup Breakpoints +break tx_application_define +break thread_0_entry +break thread_6_and_7_entry +break _tx_timer_interrupt + +# Execute to Application Definition +continue + +# Inspect mstatus once thread_0 has started +continue +print/x $mstatus + +# Verify FPU Logic and Register State exercised by thread_6/7 +continue +finish +step +step +step +print/x $mstatus +info registers float +print fpu_test_val + +# Await Timer Interrupt +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 +set $ret_addr = $ra +tbreak *$ret_addr +continue + +# 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) +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" + else + printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED\\n" + end +else + printf "PREEMPT_VERIFIED_FAIL_NULL\\n" +end + +quit +""".format(port=gdb_port, elf=elf_path) + + gdb_cmd_file = "test_cmds.gdb" + with open(gdb_cmd_file, "w") as f: + f.write(gdb_cmds) + + # 3. Run GDB + gdb_cmd = [ + gdb_bin, + "--batch", + "-x", gdb_cmd_file + ] + + print_content(f"Starting GDB: {' '.join(gdb_cmd)}") + + GDB_TIMEOUT_S = 30 + + try: + gdb_process = subprocess.run( + gdb_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + timeout=GDB_TIMEOUT_S, + ) + + print_content("GDB Output:") + print_content(gdb_process.stdout) + if gdb_process.stderr: + print_content("GDB Error Output:") + print_content(gdb_process.stderr) + + except subprocess.TimeoutExpired as e: + print_content( + f"FAILURE: GDB session exceeded {GDB_TIMEOUT_S}s timeout; " + "likely stuck on a `continue` that never matched a breakpoint." + ) + if e.stdout: + print_content("GDB Output (partial):") + print_content(e.stdout if isinstance(e.stdout, str) + else e.stdout.decode(errors='replace')) + if e.stderr: + print_content("GDB Error Output (partial):") + print_content(e.stderr if isinstance(e.stderr, str) + else e.stderr.decode(errors='replace')) + return False + + except Exception as e: + print_content(f"An error occurred during test execution: {e}") + return False + + finally: + # 4. Clean up + 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 forcefully.") + qemu_process.kill() + + # Verify results + stdout = gdb_process.stdout + timer_hit = "Breakpoint 4, _tx_timer_interrupt" in stdout + fpu_verified = False + 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: + print_content("SUCCESS: FPU instructions executed and registers inspected.") + fpu_verified = True + else: + print_content("FAILURE: Hit thread, but failed to inspect FPU. " + "Output does not contain expected value.") + + if timer_hit: + print_content("SUCCESS: Timer Interrupt verified! Hit _tx_timer_interrupt.") + else: + print_content("FAILURE: Did not hit timer interrupt.") + + if preemption_verified: + print_content("SUCCESS: Preemption verified (higher-priority thread " + "preempted a lower-priority one).") + else: + if "PREEMPT_VERIFIED_FAIL_INVERTED" in stdout: + print_content("FAILURE: Preemption inverted -- lower priority " + "thread scheduled over higher priority one.") + elif "PREEMPT_VERIFIED_FAIL_NULL" in stdout: + print_content("FAILURE: Preemption check saw NULL thread pointers.") + elif "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED" in stdout: + print_content("FAILURE: Preemption was not observed within the " + "loop budget.") + else: + print_content("FAILURE: Preemption check did not run to completion.") + + if timer_hit and fpu_verified and preemption_verified: + return True + else: + return False + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Run ThreadX RV64 QEMU/GDB Test") + parser.add_argument("--elf", required=True, help="Path to the kernel ELF file") + parser.add_argument("--qemu", default="qemu-system-riscv64", + help="Path to QEMU binary") + parser.add_argument("--gdb", default="riscv64-unknown-elf-gdb", + help="Path to GDB binary") + + args = parser.parse_args() + + success = run_qemu_test(args.elf, args.qemu, args.gdb) + + if success: + sys.exit(0) + else: + sys.exit(1) diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/trap.c b/ports/risc-v64/gnu/example_build/qemu_virt/trap.c index 5de9f37a..bdce3305 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/trap.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/trap.c @@ -1,46 +1 @@ -#include "csr.h" -#include <stdint.h> -#include "uart.h" -#include "hwtimer.h" -#include "plic.h" -#include <tx_port.h> -#include <tx_api.h> - -#define OS_IS_INTERUPT(mcause) (mcause & 0x8000000000000000ull) -#define OS_IS_EXCEPTION(mcause) (~(OS_IS_INTERUPT)) -#define OS_IS_TICK_INT(mcause) (mcause == 0x8000000000000007ull) -#define OS_IS_SOFT_INT(mcause) (mcause == 0x8000000000000003ull) -#define OS_IS_EXT_INT(mcause) (mcause == 0x800000000000000bull) -#define OS_IS_TRAP_USER(mcause) (mcause == 0x000000000000000bull) -extern void _tx_timer_interrupt(void); - -void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) -{ - if(OS_IS_INTERUPT(mcause)) - { - if(OS_IS_TICK_INT(mcause)) - { - hwtimer_handler(); - _tx_timer_interrupt(); - } - else if(OS_IS_EXT_INT(mcause)) - { - int ret = plic_irq_intr(); - if(ret) - { - puts("[INTERRUPT]: handler irq error!"); - while(1) ; - } - } - else - { - puts("[INTERRUPT]: now can't deal with the interrupt!"); - while(1) ; - } - } - else - { - puts("[EXCEPTION] : Unkown Error!!"); - while(1) ; - } -} +../../../../risc-v_common/example_build/trap/trap_qemu.c
\ No newline at end of file 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 eba6c458..a9b2fda7 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 @@ -66,6 +66,13 @@ #else addi sp, sp, -256 // Allocate space for all registers - without floating point enabled (32*8) #endif +#if defined(__riscv_vector) + /* Allocate space for vector registers */ + csrr t4, vlenb + slli t4, t4, 5 + addi t4, t4, 4*8 + sub sp, sp, t4 +#endif sd x1, 224(sp) // Store RA (28*8 = 224, because call will override ra [ra is a callee register in riscv]) @@ -150,6 +157,10 @@ _tx_initialize_low_level: csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv fscsr x0 #endif +#ifdef __riscv_vector + li t0, MSTATUS_VS + csrrs zero, mstatus, t0 // set MSTATUS_VS bit to open vector isa in riscv +#endif addi sp, sp, -8 sd ra, 0(sp) call board_init diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/uart.c b/ports/risc-v64/gnu/example_build/qemu_virt/uart.c index eea30203..1666c8c8 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/uart.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/uart.c @@ -1,100 +1 @@ -#include "uart.h" -#include "csr.h" -#include "plic.h" -#include <stdint.h> - -// the UART control registers are memory-mapped -// at address UART0. this macro returns the -// address of one of the registers. -#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg))) - -// the UART control registers. -// some have different meanings for -// read vs write. -// see http://byterunner.com/16550.html -#define RHR 0 // receive holding register (for input bytes) -#define THR 0 // transmit holding register (for output bytes) -#define IER 1 // interrupt enable register -#define IER_RX_ENABLE (1<<0) -#define IER_TX_ENABLE (1<<1) -#define FCR 2 // FIFO control register -#define FCR_FIFO_ENABLE (1<<0) -#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs -#define ISR 2 // interrupt status register -#define LCR 3 // line control register -#define LCR_EIGHT_BITS (3<<0) -#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate -#define LSR 5 // line status register -#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR -#define LSR_TX_IDLE (1<<5) // THR can accept another character to send - -#define ReadReg(reg) (*(Reg(reg))) -#define WriteReg(reg, v) (*(Reg(reg)) = (v)) - -int uart_init(void) -{ - // disable interrupts. - WriteReg(IER, 0x00); - - // special mode to set baud rate. - WriteReg(LCR, LCR_BAUD_LATCH); - - // LSB for baud rate of 38.4K. - WriteReg(0, 0x03); - - // MSB for baud rate of 38.4K. - WriteReg(1, 0x00); - - // leave set-baud mode, - // and set word length to 8 bits, no parity. - WriteReg(LCR, LCR_EIGHT_BITS); - - // reset and enable FIFOs. - WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); - - // enable transmit and receive interrupts. - // WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE); - - //enable UART0 in PLIC - plic_irq_enable(UART0_IRQ); - - //set UART0 priority in PLIC - plic_prio_set(UART0_IRQ, 1); - - //register callback for UART0 - //plic_register_callback(UART0_IRQ, uart_intr); - puts("[UART0] : Uart Init Done, this is Test output!"); - return 0; -} - -static inline void uart_putc_nolock(int ch) -{ - // wait for Transmit Holding Empty to be set in LSR. - while((ReadReg(LSR) & LSR_TX_IDLE) == 0) - ; - WriteReg(THR, ch); - return; -} - -int uart_putc(int ch) -{ - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - uart_putc_nolock(ch); - riscv_mintr_restore(intr_enable); - return 1; -} - -int uart_puts(const char* str) -{ - int i; - int intr_enable = riscv_mintr_get(); - riscv_mintr_off(); - for(i=0;str[i]!=0;i++) - { - uart_putc_nolock(str[i]); - } - uart_putc_nolock('\n'); - riscv_mintr_restore(intr_enable); - return i; -} +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.c
\ No newline at end of file diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/uart.h b/ports/risc-v64/gnu/example_build/qemu_virt/uart.h index 824f0b56..aba5ae7b 100644..120000 --- a/ports/risc-v64/gnu/example_build/qemu_virt/uart.h +++ b/ports/risc-v64/gnu/example_build/qemu_virt/uart.h @@ -1,22 +1 @@ -/*************************************************************************** - * 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 - **************************************************************************/ - -#ifndef RISCV_UART_H -#define RISCV_UART_H - -#define UART0 0x10000000L -#define UART0_IRQ 10 - -#define puts uart_puts -int uart_init(void); -int uart_putc(int ch); -int uart_puts(const char* str); -#endif +../../../../risc-v_common/example_build/uart/uart_qemu_ns16550.h
\ No newline at end of file diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index ae617b39..ac751208 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -72,20 +72,44 @@ #define VOID void +/* IMPORTANT: On this RV64 port LONG/ULONG are intentionally 32-bit (int / + * unsigned int), NOT 64-bit. ThreadX's internal data model requires LONG + * and ULONG to be exactly 4 bytes so that control-block layouts, queue + * message sizes, and the binary API remain identical to all other ThreadX + * ports. Do NOT change these to long/unsigned long — that mistake was + * already corrected once (see PR #534). Use ULONG64 for 64-bit values. */ + #ifndef __ASSEMBLER__ typedef char CHAR; typedef unsigned char UCHAR; typedef int INT; typedef unsigned int UINT; -typedef long LONG; -typedef unsigned long ULONG; +typedef int LONG; +typedef unsigned int ULONG; 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; + +/* 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 + can recover it without truncation. This mirrors the win64 port. */ +#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_extension_ptr; + +/* TX_TIMER_EXTENSION_PTR_DEFINED signals to portable code (e.g. tests) + that the timer extension pointer mechanism is in use on this port. */ +#define TX_TIMER_EXTENSION_PTR_DEFINED +#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) TX_PARAMETER_NOT_USED(timeout_input); \ + (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr; /* Define the priority levels for ThreadX. Legal values range @@ -100,7 +124,11 @@ typedef unsigned short USHORT; thread creation is less than this value, the thread create call will return an error. */ #ifndef TX_MINIMUM_STACK -#define TX_MINIMUM_STACK 1024 /* Minimum stack size for this port */ +#if defined(__riscv_vector) +#define TX_MINIMUM_STACK (1024 + 16448) /* Minimum stack size for this port */ +#else +#define TX_MINIMUM_STACK 1024 /* Minimum stack size for this port */ +#endif #endif @@ -108,7 +136,11 @@ typedef unsigned short USHORT; 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 */ +#if defined(__riscv_vector) +#define TX_TIMER_THREAD_STACK_SIZE (1024 + 16448) /* Default timer thread stack size */ +#else +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif #endif #ifndef TX_TIMER_THREAD_PRIORITY @@ -118,8 +150,13 @@ typedef unsigned short USHORT; /* Define various constants for the ThreadX RISC-V port. */ -#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ -#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */ +#ifdef TX_RISCV_SMODE +#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ +#define TX_INT_ENABLE 0x00000002 /* Enable interrupt value (SIE bit 1 of sstatus) */ +#else +#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */ +#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value (MIE bit 3 of mstatus) */ +#endif /* Define the clock source for trace event entry time stamp. The following two item are port specific. @@ -240,6 +277,19 @@ UINT _tx_thread_interrupt_control(UIN #define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; +#ifdef TX_RISCV_SMODE +#define TX_DISABLE __asm__ volatile("csrrci %0, sstatus, 2" : "=r" (interrupt_save) :: "memory"); +#define TX_RESTORE { \ + unsigned long _temp_sstatus; \ + __asm__ volatile( \ + "csrc sstatus, 2\n" \ + "andi %0, %1, 2\n" \ + "csrs sstatus, %0" \ + : "=&r" (_temp_sstatus) \ + : "r" (interrupt_save) \ + : "memory"); \ + } +#else #define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory"); #define TX_RESTORE { \ unsigned long _temp_mstatus; \ @@ -251,6 +301,7 @@ UINT _tx_thread_interrupt_control(UIN : "r" (interrupt_save) \ : "memory"); \ } +#endif /* TX_RISCV_SMODE */ #else @@ -272,12 +323,110 @@ UINT _tx_thread_interrupt_control(UIN #define TX_SEMAPHORE_DISABLE TX_DISABLE +/* Define automated coverage test extensions for the ThreadX regression test. */ + +#ifndef __ASSEMBLER__ + +typedef unsigned int TEST_FLAG; +extern TEST_FLAG threadx_byte_allocate_loop_test; +extern TEST_FLAG threadx_byte_release_loop_test; +extern TEST_FLAG threadx_mutex_suspension_put_test; +extern TEST_FLAG threadx_mutex_suspension_priority_test; +#ifndef TX_TIMER_PROCESS_IN_ISR +extern TEST_FLAG threadx_delete_timer_thread; +#endif + +extern void abort_and_resume_byte_allocating_thread(void); +extern void abort_all_threads_suspended_on_mutex(void); +extern void suspend_lowest_priority(void); +#ifndef TX_TIMER_PROCESS_IN_ISR +extern void delete_timer_thread(void); +#endif +extern TEST_FLAG test_stack_analyze_flag; +extern TEST_FLAG test_initialize_flag; +extern TEST_FLAG test_forced_mutex_timeout; + + +#ifdef TX_REGRESSION_TEST + +#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \ + { \ + pool_ptr -> tx_byte_pool_owner = TX_NULL; \ + threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \ + } + +#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \ + { \ + threadx_byte_release_loop_test = ((TEST_FLAG) 0); \ + abort_and_resume_byte_allocating_thread(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \ + abort_all_threads_suspended_on_mutex(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \ + { \ + test_forced_mutex_timeout = ((TEST_FLAG) 0); \ + _tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \ + } + +#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \ + suspend_lowest_priority(); \ + } + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \ + { \ + threadx_delete_timer_thread = ((TEST_FLAG) 0); \ + delete_timer_thread(); \ + (a) = ((UINT) 1); \ + } + +#endif + +#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \ + { \ + thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \ + { \ + stack_ptr = thread_ptr -> tx_thread_stack_start; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \ + { \ + *stack_ptr = TX_STACK_FILL; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else \ + { \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } + +#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \ + { \ + test_initialize_flag = ((TEST_FLAG) 0); \ + return; \ + } + +#endif /* TX_REGRESSION_TEST */ + +#endif /* __ASSEMBLER__ */ + + /* Define the version ID of ThreadX. This may be utilized by the application. */ #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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V64/GNU Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ 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 6aae3981..cebc8a06 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S @@ -63,7 +63,11 @@ _tx_thread_context_restore: /* Lockout interrupts. */ +#ifdef TX_RISCV_SMODE + csrci sstatus, 0x02 // Disable interrupts (SIE bit 1) +#else csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) +#endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY call _tx_execution_isr_exit // Call the ISR execution exit function @@ -74,9 +78,9 @@ _tx_thread_context_restore: { */ la t0, _tx_thread_system_state // Pickup addr of nested interrupt count - ld t1, 0(t0) // Pickup nested interrupt count + lw t1, 0(t0) // Pickup nested interrupt count addi t1, t1, -1 // Decrement the nested interrupt counter - sd t1, 0(t0) // Store new nested count + sw t1, 0(t0) // Store new nested count beqz t1, _tx_thread_not_nested_restore // If 0, not nested restore /* Interrupts are nested. */ @@ -133,6 +137,34 @@ _tx_thread_context_restore: csrw fcsr, t0 #endif +#if defined(__riscv_vector) + /* Recover vector registers v0-v31 */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 64*8 +#else + addi t1, sp, 31*8 +#endif + addi t2, t1, 4*8 + vsetvli t3, zero, e8, m8, ta, ma + vle8.v v0, (t2) // Recover v0 ~ v7 + add t2, t2, t3 + vle8.v v8, (t2) // Recover v8 ~ v15 + add t2, t2, t3 + vle8.v v16, (t2) // Recover v16 ~ v23 + add t2, t2, t3 + vle8.v v24, (t2) // Recover v24 ~ v31 + add t2, t2, t3 + + /* Recover vector CSRs */ + ld t2, 0*8(t1) + ld t3, 1*8(t1) + ld t4, 2*8(t1) + vsetvl zero, t4, t3 + csrw vstart, t2 + ld t4, 3*8(t1) + csrw vcsr, t4 +#endif + /* Recover standard registers. */ /* Restore registers, @@ -140,31 +172,46 @@ _tx_thread_context_restore: Also skip the saved registers since they have been restored by any function we called, except s0 since we use it ourselves. */ - ld t0, 30*8(sp) // Recover mepc + ld t0, 30*8(sp) // Recover exception PC +#ifdef TX_RISCV_SMODE + csrw sepc, t0 // Setup sepc + + /* Compose sstatus via read/modify/write to avoid clobbering unrelated bits. + Set SPIE and restore SPP to Supervisor, preserve other fields. */ + + csrr t1, sstatus + li t4, ~0x122 // Clear mask for SPP/SPIE/SIE + and t1, t1, t4 + li t3, 0x120 // Set SPP=Supervisor(0x100) + SPIE(0x20) so sret re-enables SIE + or t1, t1, t3 + +#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 + csrw sstatus, t1 // Update sstatus safely +#else csrw mepc, t0 // Setup mepc /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. Set MPIE and restore MPP to Machine, preserve other fields. */ csrr t1, mstatus + li t2, 0x1880 // Set MPP(0x1800) | MPIE(0x80) - /* Clear MPP/MPIE/MIE bits in t1 then set desired values. */ - - li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode (bits 12:11) - - /* Construct new mstatus in t1: clear mask bits, set MPP/MPIE and optionally FP bit, - preserve everything except the bits we will modify. */ - - li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE - and t1, t1, t4 - or t1, t1, t3 + or t1, t1, t2 // MPP and MPIE are now set. All other bits are preserved + 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 or t1, t1, t0 #endif +#if defined(__riscv_vector) + li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + or t1, t1, t0 +#endif csrw mstatus, t1 // Update mstatus safely +#endif ld ra, 28*8(sp) // Recover return address ld t0, 19*8(sp) // Recover t0 @@ -189,7 +236,26 @@ _tx_thread_context_restore: #else addi sp, sp, 32*8 // Recover stack frame - without floating point enabled #endif + +#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 + 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 + add sp, sp, t1 // Recover vector stack frame + + ld t1, 18*8(t0) // Recover t1 + ld t0, 19*8(t0) // Recover t0 +#endif +#ifdef TX_RISCV_SMODE + sret // Return to point of interrupt +#else mret // Return to point of interrupt +#endif /* } */ _tx_thread_not_nested_restore: @@ -217,7 +283,7 @@ _tx_thread_no_preempt_restore: /* Pickup the saved stack pointer. */ /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ - ld sp, 16(t1) // Switch back to thread's stack + ld sp, 8(t1) // Switch back to thread's stack /* Recover floating point registers. */ #if defined(__riscv_float_abi_single) @@ -268,29 +334,80 @@ _tx_thread_no_preempt_restore: csrw fcsr, t0 // Restore fcsr #endif +#if defined(__riscv_vector) + /* Recover vector registers v0-v31 */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 64*8 +#else + addi t1, sp, 31*8 +#endif + addi t2, t1, 4*8 + vsetvli t3, zero, e8, m8, ta, ma + vle8.v v0, (t2) // Recover v0 ~ v7 + add t2, t2, t3 + vle8.v v8, (t2) // Recover v8 ~ v15 + add t2, t2, t3 + vle8.v v16, (t2) // Recover v16 ~ v23 + add t2, t2, t3 + vle8.v v24, (t2) // Recover v24 ~ v31 + add t2, t2, t3 + + /* Recover vector CSRs */ + ld t2, 0*8(t1) + ld t3, 1*8(t1) + ld t4, 2*8(t1) + vsetvl zero, t4, t3 + csrw vstart, t2 + ld t4, 3*8(t1) + csrw vcsr, t4 +#endif + /* Recover the saved context and return to the point of interrupt. */ /* Recover standard registers. */ /* Restore registers, Skip global pointer because that does not change */ - ld t0, 30*8(sp) // Recover mepc - csrw mepc, t0 // Setup mepc + ld t0, 30*8(sp) // Recover exception PC +#ifdef TX_RISCV_SMODE + csrw sepc, t0 // Setup sepc - /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. */ + /* Compose sstatus via read/modify/write to avoid clobbering unrelated bits. */ - csrr t1, mstatus - li t2, 0x1888 // MPP(0x1800) | MPIE(0x80) | MIE(0x08) - li t3, 0x1800 // Set MPP to Machine mode - li t4, ~0x1888 // Clear mask for MPP/MPIE/MIE + csrr t1, sstatus + li t4, ~0x122 // Clear mask for SPP/SPIE/SIE and t1, t1, t4 + li t3, 0x120 // Set SPP=Supervisor(0x100) + SPIE(0x20) so sret re-enables SIE or t1, t1, t3 #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 + csrw sstatus, t1 // Update sstatus safely +#else + csrw mepc, t0 // Setup mepc + + + /* Compose mstatus via read/modify/write to avoid clobbering unrelated bits. + Set MPIE and restore MPP to Machine, preserve other fields. */ + + csrr t1, mstatus + li t2, 0x1880 // Set MPP(0x1800) | MPIE(0x80) + + or t1, t1, t2 // MPP and MPIE are now set. All other bits are preserved + 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 or t1, t1, t0 #endif +#if defined(__riscv_vector) + li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + or t1, t1, t0 +#endif csrw mstatus, t1 // Update mstatus safely +#endif ld ra, 28*8(sp) // Recover return address ld t0, 19*8(sp) // Recover t0 @@ -315,7 +432,26 @@ _tx_thread_no_preempt_restore: #else addi sp, sp, 32*8 // Recover stack frame - without floating point enabled #endif + +#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 + 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 + add sp, sp, t1 // Recover vector stack frame + + ld t1, 18*8(t0) // Recover t1 + ld t0, 19*8(t0) // Recover t0 +#endif +#ifdef TX_RISCV_SMODE + sret // Return to point of interrupt +#else mret // Return to point of interrupt +#endif /* } else @@ -324,7 +460,7 @@ _tx_thread_preempt_restore: /* Instead of directly activating the thread again, ensure we save the entire stack frame by saving the remaining registers. */ - ld t0, 16(t1) // Pickup thread's stack pointer + ld t0, 8(t1) // Pickup thread's stack pointer ori t3, zero, 1 // Build interrupt stack type sd t3, 0(t0) // Store stack type @@ -357,6 +493,36 @@ _tx_thread_preempt_restore: 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 + /* Store standard preserved registers. */ sd x9, 11*8(t0) // Store s1 @@ -377,14 +543,14 @@ _tx_thread_preempt_restore: { */ la t0, _tx_timer_time_slice // Pickup time slice variable address - ld t2, 0(t0) // Pickup time slice + lw t2, 0(t0) // Pickup time slice beqz t2, _tx_thread_dont_save_ts // If 0, skip time slice processing /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice _tx_timer_time_slice = 0; */ - sd t2, 48(t1) // Save current time slice - sd x0, 0(t0) // Clear global time slice + sw t2, 36(t1) // Save current time slice + sw x0, 0(t0) // Clear global time slice /* } */ 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 df6f2c9a..7935bfee 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -94,7 +94,11 @@ _tx_thread_context_save: sd t4, 15*8(sp) // Store t4 sd t5, 14*8(sp) // Store t5 sd t6, 13*8(sp) // Store t6 +#ifdef TX_RISCV_SMODE + csrr t0, sepc // Load exception program counter +#else csrr t0, mepc // Load exception program counter +#endif sd t0, 30*8(sp) // Save it on the stack /* Save floating point scratch registers if floating point is enabled. */ @@ -146,6 +150,36 @@ _tx_thread_context_save: sd t0, 63*8(sp) // Store fcsr #endif +#if defined(__riscv_vector) + /* Store vector registers and CSRs */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 64*8 +#else + addi t1, sp, 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 + #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY call _tx_execution_isr_enter // Call the ISR execution enter function #endif @@ -184,7 +218,11 @@ _tx_thread_not_nested_save: sd t5, 14*8(sp) // Store t5 sd t6, 13*8(sp) // Store t6 +#ifdef TX_RISCV_SMODE + csrr t1, sepc // Load exception program counter +#else csrr t1, mepc // Load exception program counter +#endif sd t1, 30*8(sp) // Save it on the stack /* Save floating point scratch registers if floating point is enabled. */ @@ -236,6 +274,36 @@ _tx_thread_not_nested_save: sd t0, 63*8(sp) // Store fcsr #endif +#if defined(__riscv_vector) + /* Store vector registers and CSRs */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 64*8 +#else + addi t1, sp, 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 + /* Save the current stack pointer in the thread's control block. */ /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ @@ -244,7 +312,7 @@ _tx_thread_not_nested_save: la t1, _tx_thread_current_ptr // Pickup current thread pointer address ld t1, 0(t1) // Pickup current thread pointer - sd sp, 16(t1) // Save stack pointer + sd sp, 8(t1) // Save stack pointer #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* _tx_execution_isr_enter is called with thread stack pointer */ @@ -275,4 +343,19 @@ _tx_thread_idle_system_save: #else addi sp, sp, 32*8 // Recover the reserved stack space #endif + +#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 + 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 + add sp, sp, t1 // Recover vector stack frame + + ld t1, 18*8(t0) // Recover t1 + ld t0, 19*8(t0) // Recover t0 +#endif ret // Return to calling ISR 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 dfcb6b47..b43d9558 100644 --- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S +++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S @@ -59,20 +59,25 @@ .global _tx_thread_interrupt_control _tx_thread_interrupt_control: /* Pickup current interrupt lockout posture. */ - /* old_mstatus = mstatus; */ +#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 + 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 +#else csrr t0, mstatus mv t1, t0 // Save original mstatus for return - - /* Apply the new interrupt posture while preserving unrelated mstatus bits. */ - /* Only modify the MIE bit (bit 3) */ - /* mstatus = (mstatus & ~MIE) | (new_posture & MIE); */ - li t2, ~0x08 // Build mask to clear MIE and t0, t0, t2 // Clear MIE bit - and a0, a0, 0x08 // Mask incoming to only MIE bit + 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 +#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 d3332896..860adf0b 100644 --- a/ports/risc-v64/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S @@ -62,7 +62,11 @@ _tx_thread_schedule: /* Enable interrupts. */ +#ifdef TX_RISCV_SMODE + csrsi sstatus, 0x02 // Enable interrupts (SIE bit 1) +#else csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3) +#endif /* Wait for a thread to execute. */ /* do @@ -94,7 +98,11 @@ _tx_thread_schedule_loop: /* Yes! We have a thread to execute. Lockout interrupts and transfer control to it. */ +#ifdef TX_RISCV_SMODE + csrci sstatus, 0x02 // Lockout interrupts +#else csrci mstatus, 0x08 // Lockout interrupts +#endif /* Setup the current thread pointer. */ /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ @@ -105,10 +113,10 @@ _tx_thread_schedule_loop: /* Increment the run count for this thread. */ /* _tx_thread_current_ptr -> tx_thread_run_count++; */ - ld t2, 8(t1) // Pickup run count - ld t3, 48(t1) // Pickup time slice value + lw t2, 4(t1) // Pickup run count + lw t3, 36(t1) // Pickup time slice value addi t2, t2, 1 // Increment run count - sd t2, 8(t1) // Store new run count + sw t2, 4(t1) // Store new run count /* Setup time-slice, if present. */ /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ @@ -118,8 +126,8 @@ _tx_thread_schedule_loop: /* Switch to the thread's stack. */ /* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ - ld sp, 16(t1) // Switch to thread's stack - sd t3, 0(t2) // Store new time-slice + ld sp, 8(t1) // Switch to thread's stack + sw t3, 0(t2) // Store new time-slice #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY @@ -206,16 +214,71 @@ _tx_thread_schedule_loop: csrw fcsr, t0 // Restore fcsr #endif +#if defined(__riscv_vector) + /* Recover vector registers v0-v31 */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 64*8 +#else + addi t1, sp, 31*8 +#endif + addi t2, t1, 4*8 + vsetvli t3, zero, e8, m8, ta, ma + vle8.v v0, (t2) // Recover v0 ~ v7 + add t2, t2, t3 + vle8.v v8, (t2) // Recover v8 ~ v15 + add t2, t2, t3 + vle8.v v16, (t2) // Recover v16 ~ v23 + add t2, t2, t3 + vle8.v v24, (t2) // Recover v24 ~ v31 + add t2, t2, t3 + + /* Recover vector CSRs */ + ld t2, 0*8(t1) + ld t3, 1*8(t1) + ld t4, 2*8(t1) + vsetvl zero, t4, t3 + csrw vstart, t2 + ld t4, 3*8(t1) + csrw vcsr, t4 +#endif + /* Recover standard registers. */ - ld t0, 30*8(sp) // Recover mepc + ld t0, 30*8(sp) // Recover mepc/sepc +#ifdef TX_RISCV_SMODE + csrw sepc, t0 // Store sepc + + /* Read/modify/write sstatus to preserve SUM, MXR, UXL, FS, etc. + Only touch SPP, SPIE, SIE — the bits SRET consumes. */ + csrr t0, sstatus + li t1, ~0x122 // Clear mask: SIE(1) | SPIE(5) | SPP(8) + and t0, t0, t1 + li t1, 0x120 // Set SPP=Supervisor(0x100) | SPIE(0x20) + or t0, t0, t1 +#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 + csrw sstatus, t0 // Update sstatus safely +#else csrw mepc, t0 // Store mepc - li t0, 0x1880 // Prepare mstatus: MPP=Machine(0x1800) | MPIE(0x80) + + /* Read/modify/write mstatus — same principle as S-mode path. */ + csrr t0, mstatus + li t1, ~0x1888 // Clear mask: MIE(3) | MPIE(7) | MPP(11:12) + and t0, t0, t1 + li t1, 0x1880 // Set MPP=Machine(0x1800) | MPIE(0x80) + or t0, t0, t1 #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t1, 0x2000 // Set FS bits for FP state + li t1, 0x6000 // Set FS=Dirty (bits 14:13) + or t0, t0, t1 +#endif +#if defined(__riscv_vector) + li t1, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state or t0, t0, t1 #endif csrw mstatus, t0 // Set mstatus +#endif ld ra, 28*8(sp) // Recover return address ld t0, 19*8(sp) // Recover t0 @@ -251,7 +314,25 @@ _tx_thread_schedule_loop: #else addi sp, sp, 32*8 // Recover stack frame - without floating point registers #endif +#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 + 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 + add sp, sp, t1 // Recover vector stack frame + + ld t1, 18*8(t0) // Recover t1 + ld t0, 19*8(t0) // Recover t0 +#endif +#ifdef TX_RISCV_SMODE + sret // Return to point of interrupt +#else mret // Return to point of interrupt +#endif _tx_thread_synch_return: @@ -287,6 +368,34 @@ _tx_thread_synch_return: csrw fcsr, t0 // #endif +#if defined(__riscv_vector) + /* Recover vector registers v0-v31 */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 28*8 +#else + addi t1, sp, 15*8 +#endif + addi t2, t1, 4*8 + vsetvli t3, zero, e8, m8, ta, ma + vle8.v v0, (t2) // Recover v0 ~ v7 + add t2, t2, t3 + vle8.v v8, (t2) // Recover v8 ~ v15 + add t2, t2, t3 + vle8.v v16, (t2) // Recover v16 ~ v23 + add t2, t2, t3 + vle8.v v24, (t2) // Recover v24 ~ v31 + add t2, t2, t3 + + /* Recover vector CSRs */ + ld t2, 0*8(t1) + ld t3, 1*8(t1) + ld t4, 2*8(t1) + vsetvl zero, t4, t3 + csrw vstart, t2 + ld t4, 3*8(t1) + csrw vcsr, t4 +#endif + /* Recover standard preserved registers. */ /* Recover standard registers. */ @@ -303,13 +412,23 @@ _tx_thread_synch_return: ld s9, 3*8(sp) // Recover s9 ld s10, 2*8(sp) // Recover s10 ld s11, 1*8(sp) // Recover s11 - ld t0, 14*8(sp) // Recover mstatus + ld t0, 14*8(sp) // Recover status register +#ifdef TX_RISCV_SMODE + csrw sstatus, t0 // Store sstatus, enables interrupt +#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 +#if defined(__riscv_vector) + 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 + add sp, sp, t1 // Recover vector stack frame +#endif ret // Return to thread /* } */ 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 8663a6f1..86cab4f0 100644 --- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S @@ -128,10 +128,19 @@ If floating point support: f30 61 Inital ft10 f31 62 Inital ft11 fscr 63 Inital fscr +If vector extension support: + vstart 64 Initial vstart + vtype 65 Initial vtype + vl 66 Initial vl + vcsr 67 Initial vcsr + v0 68 Initial v0 + v1 69 Initial v1 + ... + v31 99 Initial v31 Stack Bottom: (higher memory address) */ - ld t0, 32(a0) // Pickup end of stack area + ld t0, 24(a0) // Pickup end of stack area li t1, ~15 // Build 16-byte alignment mask and t0, t0, t1 // Make sure 16-byte alignment @@ -142,6 +151,17 @@ If floating point support: #else addi t0, t0, -32*8 // Allocate space for the stack frame #endif + +#if defined(__riscv_vector) + /* Vector extension support: calculate space based on vlenb */ + csrr t4, vlenb // Get vector register byte length + slli t4, t4, 5 // Multiply by 32 (number of vector registers) + addi t4, t4, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr + sub t0, t0, t4 // Allocate vector space for the stack frame +#else + li t4, 0 +#endif + li t1, 1 // Build stack type sd t1, 0*8(t0) // Place stack type on the top sd zero, 1*8(t0) // Initial s11 @@ -172,7 +192,7 @@ If floating point support: sd zero, 26*8(t0) // Initial a1 sd zero, 27*8(t0) // Initial a0 sd zero, 28*8(t0) // Initial ra - sd a1, 30*8(t0) // Initial mepc (thread entry point) + 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 sd zero, 32*8(t0) // Initial ft1 @@ -208,14 +228,36 @@ If floating point support: sd zero, 62*8(t0) // Initial ft11 csrr a1, fcsr // Read fcsr for initial value sd a1, 63*8(t0) // Initial fcsr - sd zero, 64*8(t0) // Reserved word (0) +#endif + +#if defined(__riscv_vector) + /* Clear vector register space */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t2, t0, 64*8 // t2 = start of vector registers +#else + addi t2, t0, 31*8 // t2 = start of vector registers +#endif + add t3, t2, t4 // t3 = end of vector registers + +vector_clear_loop: + beq t2, t3, vector_clear_done // Done if reached end + sd zero, 0(t2) // Clear 8 bytes + addi t2, t2, 8 // Move to next 8 bytes + j vector_clear_loop + +vector_clear_done: +#endif + + add t2, t0, t4 +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + sd zero, 64*8(t2) // Reserved word (0) #else - sd zero, 31*8(t0) // Reserved word (0) + sd zero, 31*8(t2) // Reserved word (0) #endif /* Setup stack pointer. */ /* thread_ptr -> tx_thread_stack_ptr = t0; */ - sd t0, 16(a0) // Save stack pointer in thread's + sd t0, 8(a0) // Save stack pointer in thread's ret // control block and return /* } */ 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 4e954ebe..583b3f3e 100644 --- a/ports/risc-v64/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S @@ -68,6 +68,12 @@ _tx_thread_system_return: #else addi sp, sp, -16*8 // Allocate space on the stack - without floating point enabled #endif +#if defined(__riscv_vector) + 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 + sub sp, sp, t1 // Allocate vector space on the stack +#endif /* Store floating point preserved registers. */ #if defined(__riscv_float_abi_single) @@ -102,6 +108,36 @@ _tx_thread_system_return: sd t0, 27*8(sp) // Store fcsr #endif +#if defined(__riscv_vector) + /* Store vector registers and CSRs */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + addi t1, sp, 28*8 +#else + addi t1, sp, 15*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 + sd zero, 0(sp) // Solicited stack type sd ra, 13*8(sp) // Save return address sd s0, 12*8(sp) // Save s0 @@ -116,6 +152,15 @@ _tx_thread_system_return: sd s9, 3*8(sp) // Save s9 sd s10, 2*8(sp) // Save s10 sd s11, 1*8(sp) // Save s11 +#ifdef TX_RISCV_SMODE + csrr t0, sstatus // Pickup sstatus + sd t0, 14*8(sp) // Save sstatus + + + /* Lockout interrupts. will be enabled in _tx_thread_schedule */ + + csrci sstatus, 0x02 // Disable interrupts (SIE bit 1) +#else csrr t0, mstatus // Pickup mstatus sd t0, 14*8(sp) // Save mstatus @@ -123,6 +168,7 @@ _tx_thread_system_return: /* Lockout interrupts. will be enabled in _tx_thread_schedule */ csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) +#endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY @@ -137,15 +183,15 @@ _tx_thread_system_return: /* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP; SP = _tx_thread_system_stack_ptr; */ - sd sp, 16(t1) // Save stack pointer - ld sp, 0(t2) // Switch to system stack + sd sp, 8(t1) // Save stack pointer + ld sp, 0(t2) // Switch to system stack /* Determine if the time-slice is active. */ /* if (_tx_timer_time_slice) { */ la t4, _tx_timer_time_slice // Pickup time slice variable addr - ld t3, 0(t4) // Pickup time slice value + lw t3, 0(t4) // Pickup time slice value la t2, _tx_thread_schedule // Pickup address of scheduling loop beqz t3, _tx_thread_dont_save_ts // If no time-slice, don't save it @@ -153,8 +199,8 @@ _tx_thread_system_return: /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; _tx_timer_time_slice = 0; */ - sd t3, 48(t1) // Save current time-slice for thread - sd zero, 0(t4) // Clear time-slice variable + sw t3, 36(t1) // Save current time-slice for thread + sw zero, 0(t4) // Clear time-slice variable /* } */ _tx_thread_dont_save_ts: diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S index 02b70461..53e572f3 100644 --- a/ports/risc-v64/gnu/src/tx_timer_interrupt.S +++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S @@ -66,11 +66,11 @@ _tx_timer_interrupt: /* _tx_timer_system_clock++; */ la t0, _tx_timer_system_clock // Pickup address of system clock - ld t1, 0(t0) // Pickup system clock + lw t1, 0(t0) // Pickup system clock la t2, _tx_timer_time_slice // Pickup address of time slice - ld t3, 0(t2) // Pickup time slice + lw t3, 0(t2) // Pickup time slice addi t1, t1, 1 // Increment system clock - sd t1, 0(t0) // Store new system clock + sw t1, 0(t0) // Store new system clock li t6, 0 // Clear local expired flag /* Test for time-slice expiration. */ @@ -83,7 +83,7 @@ _tx_timer_interrupt: /* Decrement the time_slice. */ /* _tx_timer_time_slice--; */ - sd t3, 0(t2) // Store new time slice + sw t3, 0(t2) // Store new time slice /* Check for expiration. */ /* if (_tx_timer_time_slice == 0) */ diff --git a/ports/risc-v_common/example_build/plic/plic.c b/ports/risc-v_common/example_build/plic/plic.c new file mode 100644 index 00000000..21421a72 --- /dev/null +++ b/ports/risc-v_common/example_build/plic/plic.c @@ -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 + **************************************************************************/ + +#include "plic.h" +#include <stddef.h> + +irq_callback callbacks[MAX_CALLBACK_NUM]; + +void plic_irq_enable(int irqno) +{ + int hart = riscv_get_core(); + *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno)); +} + +void plic_irq_disable(int irqno) +{ + int hart = riscv_get_core(); + *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno))); +} + +void plic_prio_set(int irqno, int prio) +{ + PLIC_SET_PRIO(irqno, prio); +} + +int plic_prio_get(int irqno) +{ + return PLIC_GET_PRIO(irqno); +} + +int plic_register_callback(int irqno, irq_callback callback) +{ + if (!(irqno >= 0 && irqno < MAX_CALLBACK_NUM)) + return -1; + callbacks[irqno] = callback; + return 0; +} + +int plic_unregister_callback(int irqno) +{ + return plic_register_callback(irqno, NULL); +} + +int plic_init(void) +{ + for (int i = 0; i < MAX_CALLBACK_NUM; i++) + callbacks[i] = NULL; + return 0; +} + +int plic_claim(void) +{ + int hart = riscv_get_core(); + return (*(uint32_t*)PLIC_MCLAIM(hart)); +} + +void plic_complete(int irqno) +{ + int hart = riscv_get_core(); + *(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; +} + +int plic_irq_intr(void) +{ + int ret = -1; + int irqno = plic_claim(); + 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 new file mode 100644 index 00000000..29d29c57 --- /dev/null +++ b/ports/risc-v_common/example_build/plic/plic.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + +#ifndef RISCV_PLIC_H +#define RISCV_PLIC_H + +#include "csr.h" +#include <stdint.h> + +#define PLIC 0x0c000000L +#define PLIC_PRIORITY (PLIC + 0x0) +#define PLIC_PENDING (PLIC + 0x1000) +#define PLIC_MENABLE(hart) (PLIC + 0x2000 + (hart)*0x100) +#define PLIC_SENABLE(hart) (PLIC + 0x2080 + (hart)*0x100) +#define PLIC_MPRIORITY(hart) (PLIC + 0x200000 + (hart)*0x2000) +#define PLIC_SPRIORITY(hart) (PLIC + 0x201000 + (hart)*0x2000) +#define PLIC_MCLAIM(hart) (PLIC + 0x200004 + (hart)*0x2000) +#define PLIC_SCLAIM(hart) (PLIC + 0x201004 + (hart)*0x2000) +#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 MAX_CALLBACK_NUM 128 +typedef int (*irq_callback)(int irqno); + +void plic_irq_enable(int irqno); +void plic_irq_disable(int irqno); +int plic_prio_get(int irqno); +void plic_prio_set(int irqno, int prio); +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-v_common/example_build/trap/trap_qemu.c b/ports/risc-v_common/example_build/trap/trap_qemu.c new file mode 100644 index 00000000..c9d8a003 --- /dev/null +++ b/ports/risc-v_common/example_build/trap/trap_qemu.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + +/* Trap handler for QEMU virt machine (RV32 and RV64). + * + * 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" +#include <stdint.h> +#include "uart.h" +#include "hwtimer.h" +#include "plic.h" +#include <tx_port.h> +#include <tx_api.h> + +#define MCAUSE_INT_BIT ((uintptr_t)1 << (__riscv_xlen - 1)) + +#define OS_IS_INTERRUPT(mcause) ((mcause) & MCAUSE_INT_BIT) +#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) + +extern void _tx_timer_interrupt(void); + +#ifdef TX_RISCV_TRAP_DEBUG +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--) + { + int d = (val >> (i * 4)) & 0xF; + uart_putc(digits[d]); + } + uart_putc('\n'); +} +#endif /* TX_RISCV_TRAP_DEBUG */ + +void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) +{ + if (OS_IS_INTERRUPT(mcause)) + { + if (OS_IS_TICK_INT(mcause)) + { + hwtimer_handler(); + _tx_timer_interrupt(); + } + else if (OS_IS_EXT_INT(mcause)) + { + int ret = plic_irq_intr(); + if (ret) + { + puts("[INTERRUPT]: handler irq error!"); + while (1) ; + } + } + else + { + puts("[INTERRUPT]: now can't deal with the interrupt!"); + while (1) ; + } + } + else + { + puts("[EXCEPTION] : Unknown Error!!"); +#ifdef TX_RISCV_TRAP_DEBUG + puts("mcause:"); + print_hex(mcause); + puts("mepc:"); + print_hex(mepc); + puts("mtval:"); + print_hex(mtval); +#else + (void)mepc; + (void)mtval; +#endif /* TX_RISCV_TRAP_DEBUG */ + while (1) ; + } +} diff --git a/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.c b/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.c new file mode 100644 index 00000000..ce9a8adb --- /dev/null +++ b/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.c @@ -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 + **************************************************************************/ + +/* NS16550-compatible UART driver for QEMU virt machine (RV32 and RV64). */ + +#include "uart.h" +#include "csr.h" +#include "plic.h" +#include <stdint.h> + +/* Memory-mapped UART control registers. */ +#define Reg(reg) ((volatile unsigned char *)(UART0 + (reg))) + +#define RHR 0 /* receive holding register (for input bytes) */ +#define THR 0 /* transmit holding register (for output bytes) */ +#define IER 1 /* interrupt enable register */ +#define IER_RX_ENABLE (1<<0) +#define IER_TX_ENABLE (1<<1) +#define FCR 2 /* FIFO control register */ +#define FCR_FIFO_ENABLE (1<<0) +#define FCR_FIFO_CLEAR (3<<1) /* clear the content of the two FIFOs */ +#define ISR 2 /* interrupt status register */ +#define LCR 3 /* line control register */ +#define LCR_EIGHT_BITS (3<<0) +#define LCR_BAUD_LATCH (1<<7) /* special mode to set baud rate */ +#define LSR 5 /* line status register */ +#define LSR_RX_READY (1<<0) /* input is waiting to be read from RHR */ +#define LSR_TX_IDLE (1<<5) /* THR can accept another character to send */ + +#define ReadReg(reg) (*(Reg(reg))) +#define WriteReg(reg, v) (*(Reg(reg)) = (v)) + +int uart_init(void) +{ + /* Disable interrupts. */ + WriteReg(IER, 0x00); + + /* Special mode to set baud rate. */ + WriteReg(LCR, LCR_BAUD_LATCH); + + /* LSB for baud rate of 38.4K. */ + WriteReg(0, 0x03); + + /* MSB for baud rate of 38.4K. */ + WriteReg(1, 0x00); + + /* Leave set-baud mode, set word length to 8 bits, no parity. */ + WriteReg(LCR, LCR_EIGHT_BITS); + + /* Reset and enable FIFOs. */ + WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); + + /* Enable UART0 in PLIC. */ + plic_irq_enable(UART0_IRQ); + + /* Set UART0 priority in PLIC. */ + plic_prio_set(UART0_IRQ, 1); + + puts("[UART0] : Uart Init Done, this is Test output!"); + return 0; +} + +/* uart_putc_nolock is static inline so it can be inlined into uart_putc + and uart_puts without introducing a public symbol. */ +static inline void uart_putc_nolock(int ch) +{ + while ((ReadReg(LSR) & LSR_TX_IDLE) == 0) + ; + WriteReg(THR, ch); +} + +int uart_putc(int ch) +{ + int intr_enable = riscv_mintr_get(); + riscv_mintr_off(); + uart_putc_nolock(ch); + riscv_mintr_restore(intr_enable); + return 1; +} + +int uart_puts(const char *str) +{ + int i; + int intr_enable = riscv_mintr_get(); + riscv_mintr_off(); + for (i = 0; str[i] != 0; i++) + uart_putc_nolock(str[i]); + uart_putc_nolock('\n'); + riscv_mintr_restore(intr_enable); + return i; +} diff --git a/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.h b/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.h new file mode 100644 index 00000000..67fc9ed9 --- /dev/null +++ b/ports/risc-v_common/example_build/uart/uart_qemu_ns16550.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + +#ifndef RISCV_UART_H +#define RISCV_UART_H + +#define UART0 0x10000000L +#define UART0_IRQ 10 + +#define puts uart_puts +int uart_init(void); +int uart_putc(int ch); +int uart_puts(const char *str); +#endif /* RISCV_UART_H */ diff --git a/ports/risc-v_common/inc/csr.h b/ports/risc-v_common/inc/csr.h new file mode 100644 index 00000000..a4495a46 --- /dev/null +++ b/ports/risc-v_common/inc/csr.h @@ -0,0 +1,356 @@ +/*************************************************************************** + * 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 + **************************************************************************/ + + +#ifndef RISCV_CSR_H +#define RISCV_CSR_H + + +/* Machine Status Register, mstatus */ +#define MSTATUS_MPP_MASK (3L << 11) /* previous mode. */ +#define MSTATUS_MPP_M (3L << 11) +#define MSTATUS_MPP_S (1L << 11) +#define MSTATUS_MPP_U (0L << 11) +#define MSTATUS_MIE (1L << 3) /* machine-mode interrupt enable. */ +#define MSTATUS_MPIE (1L << 7) +#define MSTATUS_FS (1L << 13) /* floating-point status. */ +#define MSTATUS_VS (1L << 9) /* vector status (RVV). */ + +/* Machine-mode Interrupt Enable */ +#define MIE_MTIE (1L << 7) +#define MIE_MSIE (1L << 3) +#define MIE_MEIE (1L << 11) +#define MIE_STIE (1L << 5) /* supervisor timer */ +#define MIE_SSIE (1L << 1) +#define MIE_SEIE (1L << 9) + +/* Supervisor Status Register, sstatus */ +#define SSTATUS_SPP (1L << 8) /* Previous mode, 1=Supervisor, 0=User */ +#define SSTATUS_SPIE (1L << 5) /* Supervisor Previous Interrupt Enable */ +#define SSTATUS_UPIE (1L << 4) /* User Previous Interrupt Enable */ +#define SSTATUS_SIE (1L << 1) /* Supervisor Interrupt Enable */ +#define SSTATUS_UIE (1L << 0) /* User Interrupt Enable */ + +/* Supervisor Interrupt Enable */ +#define SIE_SEIE (1L << 9) /* external */ +#define SIE_STIE (1L << 5) /* timer */ +#define SIE_SSIE (1L << 1) /* software */ + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/* All CSR accessor functions use uintptr_t so this header works for both + RV32 (uintptr_t = uint32_t) and RV64 (uintptr_t = uint64_t). */ + +static inline uintptr_t riscv_get_core(void) +{ + uintptr_t x; + asm volatile("csrr %0, mhartid" : "=r" (x)); + return x; +} + +static inline uintptr_t riscv_get_mstatus(void) +{ + uintptr_t x; + asm volatile("csrr %0, mstatus" : "=r" (x)); + return x; +} + +static inline void riscv_writ_mstatus(uintptr_t x) +{ + asm volatile("csrw mstatus, %0" : : "r" (x)); +} + +static inline void riscv_writ_mepc(uintptr_t x) +{ + asm volatile("csrw mepc, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_sstatus(void) +{ + uintptr_t x; + asm volatile("csrr %0, sstatus" : "=r" (x)); + return x; +} + +static inline void riscv_writ_sstatus(uintptr_t x) +{ + asm volatile("csrw sstatus, %0" : : "r" (x)); +} + +/* Supervisor Interrupt Pending */ +static inline uintptr_t riscv_get_sip(void) +{ + uintptr_t x; + asm volatile("csrr %0, sip" : "=r" (x)); + return x; +} + +static inline void riscv_writ_sip(uintptr_t x) +{ + asm volatile("csrw sip, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_sie(void) +{ + uintptr_t x; + asm volatile("csrr %0, sie" : "=r" (x)); + return x; +} + +static inline void riscv_writ_sie(uintptr_t x) +{ + asm volatile("csrw sie, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_mie(void) +{ + uintptr_t x; + asm volatile("csrr %0, mie" : "=r" (x)); + return x; +} + +static inline void riscv_writ_mie(uintptr_t x) +{ + asm volatile("csrw mie, %0" : : "r" (x)); +} + +/* Supervisor exception program counter */ +static inline void riscv_writ_sepc(uintptr_t x) +{ + asm volatile("csrw sepc, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_sepc(void) +{ + uintptr_t x; + asm volatile("csrr %0, sepc" : "=r" (x)); + return x; +} + +/* Machine Exception Delegation */ +static inline uintptr_t riscv_get_medeleg(void) +{ + uintptr_t x; + asm volatile("csrr %0, medeleg" : "=r" (x)); + return x; +} + +static inline void riscv_writ_medeleg(uintptr_t x) +{ + asm volatile("csrw medeleg, %0" : : "r" (x)); +} + +/* Machine Interrupt Delegation */ +static inline uintptr_t riscv_get_mideleg(void) +{ + uintptr_t x; + asm volatile("csrr %0, mideleg" : "=r" (x)); + return x; +} + +static inline void riscv_writ_mideleg(uintptr_t x) +{ + asm volatile("csrw mideleg, %0" : : "r" (x)); +} + +/* Supervisor Trap-Vector Base Address */ +static inline void riscv_writ_stvec(uintptr_t x) +{ + asm volatile("csrw stvec, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_stvec(void) +{ + uintptr_t x; + asm volatile("csrr %0, stvec" : "=r" (x)); + return x; +} + +/* Supervisor Timer Comparison Register */ +static inline uintptr_t riscv_get_stimecmp(void) +{ + uintptr_t x; + asm volatile("csrr %0, 0x14d" : "=r" (x)); + return x; +} + +static inline void riscv_writ_stimecmp(uintptr_t x) +{ + asm volatile("csrw 0x14d, %0" : : "r" (x)); +} + +/* Machine Environment Configuration Register */ +static inline uintptr_t riscv_get_menvcfg(void) +{ + uintptr_t x; + asm volatile("csrr %0, 0x30a" : "=r" (x)); + return x; +} + +static inline void riscv_writ_menvcfg(uintptr_t x) +{ + asm volatile("csrw 0x30a, %0" : : "r" (x)); +} + +/* Physical Memory Protection */ +static inline void riscv_writ_pmpcfg0(uintptr_t x) +{ + asm volatile("csrw pmpcfg0, %0" : : "r" (x)); +} + +static inline void riscv_writ_pmpaddr0(uintptr_t x) +{ + asm volatile("csrw pmpaddr0, %0" : : "r" (x)); +} + +/* Supervisor address translation and protection */ +static inline void riscv_writ_satp(uintptr_t x) +{ + asm volatile("csrw satp, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_satp(void) +{ + uintptr_t x; + asm volatile("csrr %0, satp" : "=r" (x)); + return x; +} + +/* Supervisor Trap Cause */ +static inline uintptr_t riscv_get_scause(void) +{ + uintptr_t x; + asm volatile("csrr %0, scause" : "=r" (x)); + return x; +} + +/* Supervisor Trap Value */ +static inline uintptr_t riscv_get_stval(void) +{ + uintptr_t x; + asm volatile("csrr %0, stval" : "=r" (x)); + return x; +} + +/* Machine-mode Counter-Enable */ +static inline void riscv_writ_mcounteren(uintptr_t x) +{ + asm volatile("csrw mcounteren, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_mcounteren(void) +{ + uintptr_t x; + asm volatile("csrr %0, mcounteren" : "=r" (x)); + return x; +} + +static inline uintptr_t riscv_get_time(void) +{ + uintptr_t x; + asm volatile("csrr %0, time" : "=r" (x)); + return x; +} + +static inline void riscv_sintr_on(void) +{ + uintptr_t sstatus = riscv_get_sstatus(); + sstatus |= SSTATUS_SIE; + riscv_writ_sstatus(sstatus); +} + +static inline void riscv_sintr_off(void) +{ + uintptr_t sstatus = riscv_get_sstatus(); + sstatus &= (~(uintptr_t)SSTATUS_SIE); + riscv_writ_sstatus(sstatus); +} + +static inline int riscv_sintr_get(void) +{ + uintptr_t x = riscv_get_sstatus(); + return (x & SSTATUS_SIE) != 0; +} + +static inline void riscv_sintr_restore(int x) +{ + if (x) + riscv_sintr_on(); + else + riscv_sintr_off(); +} + +static inline void riscv_mintr_on(void) +{ + uintptr_t mstatus = riscv_get_mstatus(); + mstatus |= MSTATUS_MIE; + riscv_writ_mstatus(mstatus); +} + +static inline void riscv_mintr_off(void) +{ + uintptr_t mstatus = riscv_get_mstatus(); + mstatus &= (~(uintptr_t)MSTATUS_MIE); + riscv_writ_mstatus(mstatus); +} + +static inline int riscv_mintr_get(void) +{ + uintptr_t x = riscv_get_mstatus(); + return (x & MSTATUS_MIE) != 0; +} + +static inline void riscv_mintr_restore(int x) +{ + if (x) + riscv_mintr_on(); + else + riscv_mintr_off(); +} + +static inline uintptr_t riscv_get_sp(void) +{ + uintptr_t x; + asm volatile("mv %0, sp" : "=r" (x)); + return x; +} + +/* Thread pointer (tp), used by some ports for hart-local storage. */ +static inline uintptr_t riscv_get_tp(void) +{ + uintptr_t x; + asm volatile("mv %0, tp" : "=r" (x)); + return x; +} + +static inline void riscv_writ_tp(uintptr_t x) +{ + asm volatile("mv tp, %0" : : "r" (x)); +} + +static inline uintptr_t riscv_get_ra(void) +{ + uintptr_t x; + asm volatile("mv %0, ra" : "=r" (x)); + return x; +} + +/* Flush all TLB entries. */ +static inline void sfence_vma(void) +{ + asm volatile("sfence.vma zero, zero"); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* RISCV_CSR_H */ diff --git a/ports/rxv1/ccrx/inc/tx_port.h b/ports/rxv1/ccrx/inc/tx_port.h index 295add89..160888ac 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/CCRX Version 6.5.1.202602 *"; #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 bc1f415c..846f2964 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/GNURX Version 6.5.1.202602 *"; #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 1010e464..4df3a5f9 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/IAR Version 6.5.1.202602 *"; #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 95f578eb..e06a840a 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/CCRX Version 6.5.1.202602 *"; #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 74f36a4c..22acceed 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/GNURX Version 6.5.1.202602 *"; #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 351c51d0..8f2a674c 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/IAR Version 6.5.1.202602 *"; #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 a56636bd..4f56ba74 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/CCRX Version 6.5.1.202602 *"; #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 52da26d8..6d03f0ab 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/GNURX Version 6.5.1.202602 *"; #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 e40be831..be481533 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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/IAR Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/win32/vs_2019/example_build/sample_threadx/sample_threadx.c b/ports/win32/vs_2019/example_build/sample_threadx/sample_threadx.c index 4bd7f5bc..517edbce 100644 --- a/ports/win32/vs_2019/example_build/sample_threadx/sample_threadx.c +++ b/ports/win32/vs_2019/example_build/sample_threadx/sample_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/win32/vs_2019/inc/tx_port.h b/ports/win32/vs_2019/inc/tx_port.h index 2cd61b43..167da692 100644 --- a/ports/win32/vs_2019/inc/tx_port.h +++ b/ports/win32/vs_2019/inc/tx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* tx_port.h Win32/Visual */ -/* 6.1 */ +/* 6.5.1.202602 */ /* */ /* AUTHOR */ /* */ @@ -66,6 +66,95 @@ #include <stdlib.h> #include <string.h> +/* Define automated coverage test extensions required by the regression tests. */ + +typedef unsigned int TEST_FLAG; +extern TEST_FLAG threadx_byte_allocate_loop_test; +extern TEST_FLAG threadx_byte_release_loop_test; +extern TEST_FLAG threadx_mutex_suspension_put_test; +extern TEST_FLAG threadx_mutex_suspension_priority_test; +#ifndef TX_TIMER_PROCESS_IN_ISR +extern TEST_FLAG threadx_delete_timer_thread; +#endif +extern void abort_and_resume_byte_allocating_thread(void); +extern void abort_all_threads_suspended_on_mutex(void); +extern void suspend_lowest_priority(void); +#ifndef TX_TIMER_PROCESS_IN_ISR +extern void delete_timer_thread(void); +#endif +extern TEST_FLAG test_stack_analyze_flag; +extern TEST_FLAG test_initialize_flag; +extern TEST_FLAG test_forced_mutex_timeout; + +#ifdef TX_REGRESSION_TEST + +#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \ + { \ + pool_ptr -> tx_byte_pool_owner = TX_NULL; \ + threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \ + } + +#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \ + { \ + threadx_byte_release_loop_test = ((TEST_FLAG) 0); \ + abort_and_resume_byte_allocating_thread(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \ + abort_all_threads_suspended_on_mutex(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \ + { \ + test_forced_mutex_timeout = ((TEST_FLAG) 0); \ + _tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \ + } + +#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \ + suspend_lowest_priority(); \ + } + +#ifndef TX_TIMER_PROCESS_IN_ISR +#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \ + { \ + threadx_delete_timer_thread = ((TEST_FLAG) 0); \ + delete_timer_thread(); \ + (a) = ((UINT) 1); \ + } +#endif + +#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \ + { \ + thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \ + { \ + stack_ptr = thread_ptr -> tx_thread_stack_start; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \ + { \ + *stack_ptr = TX_STACK_FILL; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else \ + { \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } + +#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \ + { \ + test_initialize_flag = ((TEST_FLAG) 0); \ + return; \ + } + +#endif + /* Define performance metric symbols. */ @@ -101,7 +190,6 @@ #define TX_TIMER_ENABLE_PERFORMANCE_INFO #endif - /* Enable trace info. */ #ifndef TX_ENABLE_EVENT_TRACE @@ -198,7 +286,7 @@ void _tx_win32_debug_entry_insert(char *action, char *file, unsigned long lin #define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024) #define TX_TRACE_TIME_MASK 0x0000FFFFUL -*/ + */ #ifndef TX_TRACE_TIME_SOURCE #define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_win32_time_stamp.LowPart)); @@ -232,7 +320,6 @@ void _tx_initialize_start_interrupts(void); #define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION _tx_initialize_start_interrupts(); - /* 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 @@ -413,7 +500,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Win32/Visual Studio Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif @@ -437,11 +524,11 @@ extern LARGE_INTEGER _tx_win32_time_stamp; #endif #ifndef TX_TIMER_PERIODIC +#ifdef TX_WIN32_SLOW_TIMER +#define TX_TIMER_PERIODIC TX_WIN32_SLOW_TIMER +#else #define TX_TIMER_PERIODIC 10 #endif - #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 dd364d06..c362b3e7 100644 --- a/ports/win32/vs_2019/src/tx_initialize_low_level.c +++ b/ports/win32/vs_2019/src/tx_initialize_low_level.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt 5.4). /**************************************************************************/ /**************************************************************************/ @@ -280,4 +281,4 @@ VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD dwUser, D /* Call ThreadX context restore for interrupt completion. */ _tx_thread_context_restore(); -}
\ No newline at end of file +} diff --git a/ports/win64/vs_2022/CMakeLists.txt b/ports/win64/vs_2022/CMakeLists.txt new file mode 100644 index 00000000..328b89d1 --- /dev/null +++ b/ports/win64/vs_2022/CMakeLists.txt @@ -0,0 +1,19 @@ +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_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/win64/vs_2022/inc/tx_port.h b/ports/win64/vs_2022/inc/tx_port.h new file mode 100644 index 00000000..4cc4e8e0 --- /dev/null +++ b/ports/win64/vs_2022/inc/tx_port.h @@ -0,0 +1,630 @@ +/*************************************************************************** + * 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.4). + * 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.h Win64/Visual */ +/* 6.5.1.202602 */ +/* */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* 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 <stdint.h> +#include <stdlib.h> +#include <string.h> + +/* Define automated coverage test extensions required by the regression tests. */ + +typedef unsigned int TEST_FLAG; +extern TEST_FLAG threadx_byte_allocate_loop_test; +extern TEST_FLAG threadx_byte_release_loop_test; +extern TEST_FLAG threadx_mutex_suspension_put_test; +extern TEST_FLAG threadx_mutex_suspension_priority_test; +#ifndef TX_TIMER_PROCESS_IN_ISR +extern TEST_FLAG threadx_delete_timer_thread; +#endif +extern void abort_and_resume_byte_allocating_thread(void); +extern void abort_all_threads_suspended_on_mutex(void); +extern void suspend_lowest_priority(void); +#ifndef TX_TIMER_PROCESS_IN_ISR +extern void delete_timer_thread(void); +#endif +extern TEST_FLAG test_stack_analyze_flag; +extern TEST_FLAG test_initialize_flag; +extern TEST_FLAG test_forced_mutex_timeout; + +#ifdef TX_REGRESSION_TEST + +#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \ + { \ + pool_ptr -> tx_byte_pool_owner = TX_NULL; \ + threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \ + } + +#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \ + { \ + threadx_byte_release_loop_test = ((TEST_FLAG) 0); \ + abort_and_resume_byte_allocating_thread(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \ + abort_all_threads_suspended_on_mutex(); \ + } + +#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \ + { \ + test_forced_mutex_timeout = ((TEST_FLAG) 0); \ + _tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \ + } + +#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \ + { \ + threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \ + suspend_lowest_priority(); \ + } + +#ifndef TX_TIMER_PROCESS_IN_ISR +#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \ + { \ + threadx_delete_timer_thread = ((TEST_FLAG) 0); \ + delete_timer_thread(); \ + (a) = ((UINT) 1); \ + } +#endif + +#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \ + { \ + thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \ + { \ + stack_ptr = thread_ptr -> tx_thread_stack_start; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \ + { \ + *stack_ptr = TX_STACK_FILL; \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } \ + else \ + { \ + test_stack_analyze_flag = ((TEST_FLAG) 0); \ + } + +#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \ + { \ + test_initialize_flag = ((TEST_FLAG) 0); \ + return; \ + } + +#endif + + +/* Define 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 + + + +/* 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; +typedef uint64_t ULONG64; +#define ULONG64_DEFINED + + +/* Override the alignment type to preserve pointer-sized alignment on LLP64. */ + +#define ALIGN_TYPE_DEFINED +typedef unsigned long long ALIGN_TYPE; + + +/* Override the free block marker for byte pools to be a 64-bit constant. */ + +#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEEULL) + + +/* Add Win32 debug insert prototype. */ + +void _tx_win32_debug_entry_insert(char *action, char *file, unsigned long line); + +#ifndef TX_WIN32_DEBUG_ENABLE + +/* If Win32 debug is not enabled, turn logging into white-space. */ + +#define _tx_win32_debug_entry_insert(a, b, c) + +#endif + + +/* Define the TX_MEMSET macro to remove library reference. */ + +#define TX_MEMSET(a,b,c) { \ + UCHAR *ptr; \ + UCHAR value; \ + UINT i, size; \ + ptr = (UCHAR *) ((VOID *) a); \ + value = (UCHAR) b; \ + size = (UINT) c; \ + for (i = 0; i < size; i++) \ + { \ + *ptr++ = value; \ + } \ + } + + +/* Include windows include file. */ + +#include <windows.h> + +#ifndef TX_WIN32_USE_HIGH_RESOLUTION_TIMER +#define TX_WIN32_USE_HIGH_RESOLUTION_TIMER 1 +#endif + +#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION +#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002UL +#endif + + +/* 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 400 /* Default timer thread stack size - Not used in Win64 port! */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + + +/* Define various constants for the ThreadX 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 *((ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + + */ + +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_win32_time_stamp.LowPart)) +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port-specific trace extension to pickup the Windows timer. */ + +#define TX_TRACE_PORT_EXTENSION QueryPerformanceCounter((LARGE_INTEGER *)&_tx_win32_time_stamp); + + +/* 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. */ + +#define TX_INLINE_INITIALIZATION + + +/* Define the Win32-specific initialization code that is expanded in the generic source. */ + +void _tx_initialize_start_interrupts(void); + +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION _tx_initialize_start_interrupts(); + +/* 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. */ + +#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_2 +#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 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) + + +/* Preserve the thread timeout pointer on LLP64 targets. */ + +#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; + DWORD tx_win32_critical_section_owner; + ULONG tx_win32_critical_section_nested_count; +} TX_WIN32_CRITICAL_SECTION; + + +/* Define Win32-specific critical section APIs. */ + +void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_section); +void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_section); +void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section); + + +/* Define post completion processing for tx_thread_delete, so that the Win32 thread resources are properly removed. */ + +#define TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) \ +{ \ +BOOL win32_status; \ +DWORD exitcode; \ +HANDLE threadrunsemaphore; \ +HANDLE threadhandle; \ +ULONG wait_count; \ + threadhandle = thread_ptr -> tx_thread_win32_thread_handle; \ + threadrunsemaphore = thread_ptr -> tx_thread_win32_thread_run_semaphore; \ + if ((threadhandle != ((HANDLE) 0)) || (threadrunsemaphore != ((HANDLE) 0)))\ + { \ + _tx_thread_interrupt_restore(tx_saved_posture); \ + if (threadhandle != ((HANDLE) 0)) \ + { \ + wait_count = ((ULONG) 0); \ + do \ + { \ + win32_status = GetExitCodeThread(threadhandle, &exitcode); \ + if ((win32_status) && (exitcode != STILL_ACTIVE)) \ + { \ + break; \ + } \ + ResumeThread(threadhandle); \ + if (threadrunsemaphore != ((HANDLE) 0)) \ + { \ + ReleaseSemaphore(threadrunsemaphore, 1, NULL); \ + } \ + Sleep(1); \ + wait_count++; \ + } while (wait_count < ((ULONG) 100)); \ + win32_status = GetExitCodeThread(threadhandle, &exitcode); \ + if ((win32_status) && (exitcode == STILL_ACTIVE)) \ + { \ + (void) TerminateThread(threadhandle, 0U); \ + (void) WaitForSingleObject(threadhandle, INFINITE); \ + } \ + CloseHandle(threadhandle); \ + } \ + if (threadrunsemaphore != ((HANDLE) 0)) \ + { \ + CloseHandle(threadrunsemaphore); \ + } \ + tx_saved_posture = _tx_thread_interrupt_disable(); \ + } \ +} + + +/* Define post completion processing for tx_thread_reset, so that the Win32 thread resources are properly removed. */ + +#define TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) \ +{ \ +BOOL win32_status; \ +DWORD exitcode; \ +HANDLE threadrunsemaphore; \ +HANDLE threadhandle; \ +ULONG wait_count; \ + threadhandle = thread_ptr -> tx_thread_win32_thread_handle; \ + threadrunsemaphore = thread_ptr -> tx_thread_win32_thread_run_semaphore; \ + if ((threadhandle != ((HANDLE) 0)) || (threadrunsemaphore != ((HANDLE) 0)))\ + { \ + _tx_thread_interrupt_restore(tx_saved_posture); \ + if (threadhandle != ((HANDLE) 0)) \ + { \ + wait_count = ((ULONG) 0); \ + do \ + { \ + win32_status = GetExitCodeThread(threadhandle, &exitcode); \ + if ((win32_status) && (exitcode != STILL_ACTIVE)) \ + { \ + break; \ + } \ + ResumeThread(threadhandle); \ + if (threadrunsemaphore != ((HANDLE) 0)) \ + { \ + ReleaseSemaphore(threadrunsemaphore, 1, NULL); \ + } \ + Sleep(1); \ + wait_count++; \ + } while (wait_count < ((ULONG) 100)); \ + win32_status = GetExitCodeThread(threadhandle, &exitcode); \ + if ((win32_status) && (exitcode == STILL_ACTIVE)) \ + { \ + (void) TerminateThread(threadhandle, 0U); \ + (void) WaitForSingleObject(threadhandle, INFINITE); \ + } \ + CloseHandle(threadhandle); \ + } \ + if (threadrunsemaphore != ((HANDLE) 0)) \ + { \ + CloseHandle(threadrunsemaphore); \ + } \ + tx_saved_posture = _tx_thread_interrupt_disable(); \ + } \ +} + + +/* 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. */ + +UINT _tx_thread_interrupt_disable(void); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA UINT tx_saved_posture; + +#define TX_DISABLE tx_saved_posture = _tx_thread_interrupt_disable(); + +#define TX_RESTORE _tx_thread_interrupt_restore(tx_saved_posture); + + +/* 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 utilized by the application. */ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2026 Eclipse ThreadX contributors. * ThreadX Win64/MSVC Version 6.5.1.202602 *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +/* Define externals for the Win32 port of ThreadX. */ + +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_waiting; +extern UINT _tx_win32_timer_id; +extern LARGE_INTEGER _tx_win32_time_stamp; + + +#ifndef TX_WIN32_MEMORY_SIZE +#define TX_WIN32_MEMORY_SIZE 64000 +#endif + +VOID _tx_win32_scheduler_wake(VOID); + +#ifndef TX_TIMER_PERIODIC +#ifdef TX_WIN32_SLOW_TIMER +#define TX_TIMER_PERIODIC TX_WIN32_SLOW_TIMER +#else +#define TX_TIMER_PERIODIC 10 +#endif +#endif + +#endif + + + + + + + + + + + + + + diff --git a/ports/win64/vs_2022/src/tx_initialize_low_level.c b/ports/win64/vs_2022/src/tx_initialize_low_level.c new file mode 100644 index 00000000..b7e96575 --- /dev/null +++ b/ports/win64/vs_2022/src/tx_initialize_low_level.c @@ -0,0 +1,417 @@ +/*************************************************************************** + * 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.4). + * 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 Codex (gpt 5.4). +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#pragma comment (lib, "Winmm.lib") + +/* Define various Win32 objects used by the ThreadX port. */ + +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; + + +/* 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_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 + +extern ULONG _tx_thread_system_state; +extern UINT _tx_thread_preempt_disable; +extern TX_THREAD *_tx_thread_current_ptr; +extern TX_THREAD *_tx_thread_execute_ptr; + + +/* Define the maximum size of the Win32 debug array. */ + +#ifndef TX_WIN32_DEBUG_EVENT_SIZE +#define TX_WIN32_DEBUG_EVENT_SIZE 400 +#endif + + +/* Define debug log in order to debug Win32 issues with this port. */ + +typedef struct TX_WIN32_DEBUG_ENTRY_STRUCT +{ + char *tx_win32_debug_entry_action; + LARGE_INTEGER tx_win32_debug_entry_timestamp; + char *tx_win32_debug_entry_file; + unsigned long tx_win32_debug_entry_line; + TX_WIN32_CRITICAL_SECTION tx_win32_debug_entry_critical_section; + unsigned long tx_win32_debug_entry_int_disabled_flag; + ULONG tx_win32_debug_entry_system_state; + UINT tx_win32_debug_entry_preempt_disable; + TX_THREAD *tx_win32_debug_entry_current_thread; + DWORD tx_win32_debug_entry_current_thread_id; + TX_THREAD *tx_win32_debug_entry_execute_thread; + DWORD tx_win32_debug_entry_execute_thread_id; + DWORD tx_win32_debug_entry_running_id; +} TX_WIN32_DEBUG_ENTRY; + + +/* Define the circular array of Win32 debug entries. */ + +TX_WIN32_DEBUG_ENTRY _tx_win32_debug_entry_array[TX_WIN32_DEBUG_EVENT_SIZE]; + + +/* Define the Win32 debug index. */ + +unsigned long _tx_win32_debug_entry_index = 0; + + +/* Now define the debug entry function. */ +void _tx_win32_debug_entry_insert(char *action, char *file, unsigned long line) +{ + + + /* Get the time stamp. */ + QueryPerformanceCounter((LARGE_INTEGER *)&_tx_win32_time_stamp); + + /* Setup the debug entry. */ + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_action = action; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_timestamp = _tx_win32_time_stamp; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_file = file; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_line = line; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_critical_section = _tx_win32_critical_section; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_int_disabled_flag = _tx_win32_global_int_disabled_flag; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_system_state = _tx_thread_system_state; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_preempt_disable = _tx_thread_preempt_disable; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread = _tx_thread_current_ptr; + if (_tx_thread_current_ptr) + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread_id = _tx_thread_current_ptr -> tx_thread_win32_thread_id; + else + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_current_thread_id = 0; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread = _tx_thread_execute_ptr; + if (_tx_thread_execute_ptr) + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread_id = _tx_thread_execute_ptr -> tx_thread_win32_thread_id; + else + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_execute_thread_id = 0; + _tx_win32_debug_entry_array[_tx_win32_debug_entry_index].tx_win32_debug_entry_running_id = GetCurrentThreadId(); + + /* Now move to the next entry. */ + _tx_win32_debug_entry_index++; + + /* Determine if we need to wrap the list. */ + if (_tx_win32_debug_entry_index >= TX_WIN32_DEBUG_EVENT_SIZE) + { + + /* Yes, wrap the list! */ + _tx_win32_debug_entry_index = 0; + } +} + +#endif + + +/* Define the ThreadX timer interrupt handler. */ + +void _tx_timer_interrupt(void); + + +/* Define other external function references. */ + +VOID _tx_initialize_low_level(VOID); +VOID _tx_thread_context_save(VOID); +VOID _tx_thread_context_restore(VOID); +VOID _tx_win32_scheduler_wake(VOID); + + +/* Define other external variable references. */ + +extern VOID *_tx_initialize_unused_memory; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, 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 */ +/* */ +/* CreateMutex Win32 create mutex */ +/* CreateThread Win32 create thread */ +/* CreateSemaphore Win32 create semaphore */ +/* GetCurrentThreadId Win32 get current thread ID */ +/* SetProcessAffinityMask Win32 process affinity set */ +/* SetThreadPriority Win32 set thread priority */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ +VOID _tx_initialize_low_level(VOID) +{ + +/* Deprecate TX_WIN32_MULTI_CORE build option and default to restricting + execution to one core. */ + +#ifndef TX_WIN32_BYPASS_AFFINITY_SETUP + + /* Limit this ThreadX simulation on Win64 to a single core. */ + if (SetProcessAffinityMask(GetCurrentProcess(), ((DWORD_PTR) 1)) == 0) + { + + /* Error restricting the process to one core. */ + printf("ThreadX Win64 error restricting the process to one core!\n"); + while(1) + { + } + } +#endif + + /* Pickup the first available memory address. */ + + /* Save the first available memory address. */ + _tx_initialize_unused_memory = malloc(TX_WIN32_MEMORY_SIZE); + + /* 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, + analogous to an interrupt lockout on an embedded target. */ + _tx_win32_critical_section.tx_win32_critical_section_mutex_handle = CreateMutex(NULL, FALSE, NULL); + _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); + _tx_win32_isr_semaphore = CreateSemaphore(NULL, 0, 1, NULL); + if ((_tx_win32_scheduler_semaphore == NULL) || (_tx_win32_isr_semaphore == NULL)) + { + printf("ThreadX Win64 error creating semaphores!\n"); + while(1) + { + } + } + + /* 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 Win64 error creating scheduler wake event!\n"); + while(1) + { + } + } + + /* Initialize the global interrupt disabled flag. */ + _tx_win32_global_int_disabled_flag = TX_FALSE; + _tx_win32_timer_waiting = TX_FALSE; + + /* Done, return to caller. */ +} + + +/* 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. */ + +void _tx_initialize_start_interrupts(void) +{ + TIMECAPS tc; + UINT wTimerRes; + + /* Queries the timer device to determine its resolution. */ + if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) + { + /* Error; application can't continue. */ + printf("Query timer device error."); + while (1) + { + } + } + + wTimerRes = min(max(tc.wPeriodMin, TX_TIMER_PERIODIC), tc.wPeriodMax); + + /* Request the best available timer resolution for the simulation. */ + if (timeBeginPeriod(wTimerRes) != TIMERR_NOERROR) + { + printf("ThreadX Win64 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 Win64 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 Win64 error creating timer thread!\n"); + while (1) + { + } + } + + SetThreadPriority(_tx_win32_timer_thread_handle, THREAD_PRIORITY_HIGHEST); + + _tx_win32_timer_id = 1; + + /* 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_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); + + /* Call ThreadX context save for interrupt preparation. */ + _tx_thread_context_save(); + + /* Call the ThreadX system timer interrupt processing. */ + _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. */ + while (1) + { + WaitForSingleObject(_tx_win32_timer_handle, INFINITE); + _tx_win32_timer_interrupt(0, 0, 0, 0, 0); + _tx_win32_timer_start(); + } +} + + +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 Win64 error starting timer!\n"); + while (1) + { + } + } +} + diff --git a/ports/win64/vs_2022/src/tx_thread_context_restore.c b/ports/win64/vs_2022/src/tx_thread_context_restore.c new file mode 100644 index 00000000..9786e7cb --- /dev/null +++ b/ports/win64/vs_2022/src/tx_thread_context_restore.c @@ -0,0 +1,180 @@ +/*************************************************************************** + * 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.4). + * 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 Codex (gpt 5.4). + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* 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 */ +/* */ +/* ReleaseSemaphore Win32 release semaphore */ +/* ResumeThread Win32 resume thread */ +/* _tx_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/**************************************************************************/ +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. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + + /* Debug entry. */ + _tx_win32_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__); + + /* 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)) + { + + /* Yes, this is the first and last interrupt processed. */ + + /* Check to see if preemption is required. */ + if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr)) + { + + /* Preempt the running application thread. We don't need to suspend the + application thread since that is done in the context save processing. */ + + /* Indicate that this thread was suspended asynchronously. */ + _tx_thread_current_ptr -> tx_thread_win32_suspension_type = 1; + + /* Save the remaining time-slice and disable it. */ + if (_tx_timer_time_slice) + { + + _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; + _tx_timer_time_slice = 0; + } + + /* 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)) + { + + /* Release the critical section while the scheduler runs. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE); + _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 + { + + /* Since preemption is not required, resume the interrupted thread. */ + 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) + { + + /* Release the critical section while the scheduler runs. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE); + _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/risc-v32/clang/src/tx_thread_interrupt_control.S b/ports/win64/vs_2022/src/tx_thread_context_save.c index 86b6745e..84f2d290 100644 --- a/ports/risc-v32/clang/src/tx_thread_interrupt_control.S +++ b/ports/win64/vs_2022/src/tx_thread_context_save.c @@ -1,14 +1,18 @@ /*************************************************************************** - * Copyright (c) 2026 Quintauris - * + * 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 + * + * AI Disclosure: This file was largely AI-generated by Codex (gpt 5.4). + * 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 **************************************************************************/ - /**************************************************************************/ /**************************************************************************/ /** */ @@ -20,69 +24,88 @@ /**************************************************************************/ - .section .text +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_interrupt_control RISC-V32/GNU */ -/* 6.4.x */ +/* _tx_thread_context_save Win64/MSVC */ +/* 6.1 */ /* AUTHOR */ /* */ -/* Francisco Merino, Quintauris */ +/* William E. Lamie, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function is responsible for changing the interrupt lockout */ -/* posture of the system. */ +/* 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 */ /* */ -/* new_posture New interrupt lockout posture */ +/* None */ /* */ /* OUTPUT */ /* */ -/* old_posture Old interrupt lockout posture */ +/* None */ /* */ /* CALLS */ /* */ -/* None */ +/* SuspendThread Win32 thread suspend */ +/* _tx_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ /* */ /* CALLED BY */ /* */ -/* Application Code */ +/* ISRs */ /* */ /**************************************************************************/ -/* UINT _tx_thread_interrupt_control(UINT new_posture) -{ */ - .global _tx_thread_interrupt_control -_tx_thread_interrupt_control: +VOID _tx_thread_context_save(VOID) +{ + +TX_THREAD *thread_ptr; - /* Pickup current interrupt posture. */ - csrr a1, mstatus // Pickup mstatus - andi a1, a1, 0x08 // Mask out all but MIE + /* Enter critical section to ensure other threads are not playing with + the core ThreadX data structures. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); - /* Check for the new posture. */ + /* Debug entry. */ + _tx_win32_debug_entry_insert("CONTEXT_SAVE", __FILE__, __LINE__); - beqz a0, _tx_thread_interrupt_disable // If 0, disable interrupts + /* Pickup the current thread pointer. */ + thread_ptr = _tx_thread_current_ptr; - /* Enable interrupts. */ + /* If an application thread is running, suspend it to simulate preemption. */ + if ((thread_ptr) && (_tx_thread_system_state == 0)) + { - csrsi mstatus, 0x08 // Enable interrupts (MIE bit 3) - j _tx_thread_interrupt_control_exit // Return to caller + /* Yes, this is the first interrupt and an application thread is running... + suspend it! */ -_tx_thread_interrupt_disable: + /* Suspend the thread to simulate preemption. Note that the thread is suspended BEFORE the protection get + flag is checked to ensure there is not a race condition between this thread and the update of that flag. */ + SuspendThread(thread_ptr -> tx_thread_win32_thread_handle); - /* Disable interrupts. */ + /* Debug entry. */ + _tx_win32_debug_entry_insert("CONTEXT_SAVE-suspend_thread", __FILE__, __LINE__); - csrci mstatus, 0x08 // Disable interrupts (MIE bit 3) + } -_tx_thread_interrupt_control_exit: + /* Increment the nested interrupt condition. */ + _tx_thread_system_state++; - /* Return the old interrupt posture. */ + /* Exit Win32 critical section. */ + _tx_win32_critical_section_release(&_tx_win32_critical_section); +} - mv a0, a1 // Setup return value - ret // Return to caller -/* } */ diff --git a/ports/win64/vs_2022/src/tx_thread_interrupt_control.c b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c new file mode 100644 index 00000000..ab50a3c9 --- /dev/null +++ b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c @@ -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 Codex (gpt 5.4). + * 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 */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + +#include <winbase.h> + +/* Define small routines used for the TX_DISABLE/TX_RESTORE macros. */ + +UINT _tx_thread_interrupt_disable(void) +{ + +UINT previous_value; + + + previous_value = _tx_thread_interrupt_control(TX_INT_DISABLE); + return(previous_value); +} + + +VOID _tx_thread_interrupt_restore(UINT previous_posture) +{ + + previous_posture = _tx_thread_interrupt_control(previous_posture); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* 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 */ +/* */ +/* ExitThread Win32 thread exit */ +/* GetCurrentThread Win32 get current thread */ +/* GetCurrentThreadId Win32 get current thread ID */ +/* GetThreadPriority Win32 get thread priority */ +/* _tx_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ +/* _tx_win32_critical_section_release_all */ +/* Release critical section */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _tx_thread_interrupt_control(UINT new_posture) +{ + +UINT old_posture; +HANDLE threadhandle; +int threadpriority; +DWORD threadid; +TX_THREAD *thread_ptr; + + + /* Enter Win32 critical section. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + +#ifdef TX_WIN32_DEBUG_ENABLE + + /* Determine if this is a disable or enable request. */ + if (new_posture == TX_INT_ENABLE) + { + /* Enable. */ + _tx_win32_debug_entry_insert("RESTORE", __FILE__, __LINE__); + } + else + { + /* Disable. */ + _tx_win32_debug_entry_insert("DISABLE", __FILE__, __LINE__); + } +#endif + + /* 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))) + { + + /* This indicates the Win32 thread was actually terminated by ThreadX is only + being allowed to run in order to cleanup its resources. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + + /* Exit this thread. */ + ExitThread(0); + } + + /* Determine the current interrupt lockout condition. */ + if (_tx_win32_critical_section.tx_win32_critical_section_nested_count == 1) + { + + /* First pass through, interrupts are enabled. */ + old_posture = TX_INT_ENABLE; + } + else + { + + /* Interrupts are disabled. */ + old_posture = TX_INT_DISABLE; + } + + /* First, determine if this call is from a non-thread. */ + if (_tx_thread_system_state) + { + + /* Determine how to apply the new posture. */ + if (new_posture == TX_INT_ENABLE) + { + + /* Clear the disabled flag. */ + _tx_win32_global_int_disabled_flag = TX_FALSE; + + /* Determine if the critical section is locked. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + } + else if (new_posture == TX_INT_DISABLE) + { + + /* Set the disabled flag. */ + _tx_win32_global_int_disabled_flag = TX_TRUE; + } + } + else if (thread_ptr) + { + + /* Determine how to apply the new posture. */ + if (new_posture == TX_INT_ENABLE) + { + + /* Clear the disabled flag. */ + _tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag = TX_FALSE; + + /* Determine if the critical section is locked. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + } + else if (new_posture == TX_INT_DISABLE) + { + + /* Set the disabled flag. */ + _tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag = TX_TRUE; + } + } + + /* Return the previous interrupt disable posture. */ + 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 new file mode 100644 index 00000000..d08305ee --- /dev/null +++ b/ports/win64/vs_2022/src/tx_thread_schedule.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 Codex (gpt 5.4). + * 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 Codex (gpt 5.4). + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" + + +static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* 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 */ +/* */ +/* ReleaseSemaphore Win32 release semaphore */ +/* ResumeThread Win32 resume thread */ +/* _tx_win32_scheduler_wake Wake scheduler waiters */ +/* WaitForSingleObject Win32 wait on a semaphore */ +/* _tx_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ +VOID _tx_thread_schedule(VOID) +{ +DWORD wait_status; + + + /* Loop forever. */ + while(1) + { + + /* Wait for a thread to execute and all ISRs to complete. */ + while(1) + { + + + /* Enter Win32 critical section. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SCHEDULE-wake_up", __FILE__, __LINE__); + + /* Determine if there is a thread ready to execute AND all ISRs + are complete. */ + if ((_tx_thread_execute_ptr != TX_NULL) && (_tx_thread_system_state == 0)) + { + + /* Get out of this loop and schedule the thread! */ + break; + } + else + { + + /* 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); + } + } + + /* Yes! We have a thread to execute. Note that the critical section is already + active from the scheduling loop above. */ + + /* Setup the current thread pointer. */ + _tx_thread_current_ptr = _tx_thread_execute_ptr; + + /* Increment the run count for this thread. */ + _tx_thread_current_ptr -> tx_thread_run_count++; + + /* Setup time-slice, if present. */ + _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; + + /* Determine how the thread was suspended. */ + if (_tx_thread_current_ptr -> tx_thread_win32_suspension_type) + { + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SCHEDULE-resume_thread", __FILE__, __LINE__); + + /* Pseudo interrupt suspension. The thread is not waiting on + its run semaphore. */ + ResumeThread(_tx_thread_current_ptr -> tx_thread_win32_thread_handle); + } + else + { + + /* 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. */ + 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. */ + _tx_win32_debug_entry_insert("SCHEDULE-self_suspend_sem", __FILE__, __LINE__); + + /* 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); + } +} + + +static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle) +{ + + /* 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()) + { + + /* Simply increment the nested counter. */ + critical_section -> tx_win32_critical_section_nested_count++; + } + else + { + + /* 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) + { + } + } + + /* At this point we have the mutex. */ + + /* Increment the nesting counter. */ + critical_section -> tx_win32_critical_section_nested_count = 1; + + /* Remember the owner. */ + critical_section -> tx_win32_critical_section_owner = GetCurrentThreadId(); + } +} + + +void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_section) +{ + + + /* Ensure the caller is the mutex owner. */ + if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) + { + + /* Determine if there is protection. */ + if (critical_section -> tx_win32_critical_section_nested_count) + { + + /* Decrement the nesting counter. */ + critical_section -> tx_win32_critical_section_nested_count--; + + /* Determine if the critical section is now being released. */ + if (critical_section -> tx_win32_critical_section_nested_count == 0) + { + + /* 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++; + } + } + } + } + else + { + + /* Increment the system error counter. */ + _tx_win32_system_error++; + } +} + + +void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section) +{ + + /* Ensure the caller is the mutex owner. */ + if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) + { + + /* Determine if there is protection. */ + if (critical_section -> tx_win32_critical_section_nested_count) + { + + /* Clear the nesting counter. */ + critical_section -> tx_win32_critical_section_nested_count = 0; + + /* 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++; + } + } + } + else + { + + /* Increment the system error counter. */ + _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 new file mode 100644 index 00000000..c50f7754 --- /dev/null +++ b/ports/win64/vs_2022/src/tx_thread_stack_build.c @@ -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 Codex (gpt 5.4). + * 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 Codex (gpt 5.4). + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include <stdio.h> + + +/* Prototype for new thread entry function. */ + +DWORD WINAPI _tx_win32_thread_entry(LPVOID p); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* 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 */ +/* */ +/* CreateThread Win32 create thread */ +/* ResumeThread Win32 resume thread */ +/* SetThreadPriority Win32 set thread priority */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* _tx_thread_reset Reset thread service */ +/* */ +/**************************************************************************/ +VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +{ + + /* Create a Win32 thread for the application thread. */ + thread_ptr -> tx_thread_win32_thread_handle = + CreateThread(NULL, 0, _tx_win32_thread_entry, (LPVOID) thread_ptr, CREATE_SUSPENDED, + &(thread_ptr -> tx_thread_win32_thread_id)); + + /* Check for a good thread create. */ + if (!thread_ptr -> tx_thread_win32_thread_handle) + { + + /* Display an error message. */ + printf("ThreadX Win32 error creating thread!\n"); + while(1) + { + } + } + + /* Otherwise, we have a good thread create. Now set the priority to + a lower level. */ + SetThreadPriority(thread_ptr -> tx_thread_win32_thread_handle, THREAD_PRIORITY_LOWEST); + + /* Create the run semaphore for the thread. This will allow the scheduler + control over when the thread actually runs. */ + thread_ptr -> tx_thread_win32_thread_run_semaphore = CreateSemaphore(NULL, 0, 1, NULL); + + /* Determine if the run semaphore was created successfully. */ + if (!thread_ptr -> tx_thread_win32_thread_run_semaphore) + { + + /* Display an error message. */ + printf("ThreadX Win32 error creating thread running semaphore!\n"); + while(1) + { + } + } + + /* 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; + + /* Clear the disabled count that will keep track of the + 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); + + /* Clear the first word of the stack. */ + *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; + + /* 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 *current_thread_ptr; +HANDLE threadhandle; +int threadpriority; +DWORD threadid; + + /* Pickup the current thread pointer. */ + thread_ptr = (TX_THREAD *) ptr; + + /* 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); + + /* 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); + + /* 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/win64/vs_2022/src/tx_thread_system_return.c b/ports/win64/vs_2022/src/tx_thread_system_return.c new file mode 100644 index 00000000..7a8fc89c --- /dev/null +++ b/ports/win64/vs_2022/src/tx_thread_system_return.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 Codex (gpt 5.4). + * 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 Codex (gpt 5.4). + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include <stdio.h> + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the 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_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ +/* _tx_win32_critical_section_release_all */ +/* Release critical section */ +/* ExitThread Win32 thread exit */ +/* GetCurrentThread Win32 get current thread */ +/* GetCurrentThreadId Win32 get current thread ID */ +/* GetThreadPriority Win32 get thread priority */ +/* ReleaseSemaphore Win32 release semaphore */ +/* WaitForSingleObject Win32 wait on semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/* */ +/**************************************************************************/ +VOID _tx_thread_system_return(VOID) +{ + +TX_THREAD *temp_thread_ptr; +HANDLE temp_run_semaphore; +UINT temp_thread_state; +HANDLE threadhandle; +int threadpriority; +DWORD threadid; + + + /* Enter Win32 critical section. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + + /* Pickup the handle of the current thread. */ + threadhandle = GetCurrentThread(); + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SYSTEM_RETURN", __FILE__, __LINE__); + + /* First, determine if the thread was terminated. */ + + /* Pickup the priority of the current thread. */ + threadpriority = GetThreadPriority(threadhandle); + + /* Pickup the ID of the current thread. */ + threadid = GetCurrentThreadId(); + + /* Pickup the current thread pointer. */ + temp_thread_ptr = _tx_thread_current_ptr; + + /* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not + match the current thread pointer. */ + if ((threadpriority == THREAD_PRIORITY_LOWEST) && + ((!temp_thread_ptr) || (temp_thread_ptr -> tx_thread_win32_thread_id != threadid))) + { + + /* This indicates the Win32 thread was actually terminated by ThreadX and is only + being allowed to run in order to cleanup its resources. */ + + /* Release critical section. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + + /* Exit thread. */ + ExitThread(0); + } + + /* Determine if the time-slice is active. */ + if (_tx_timer_time_slice) + { + + /* Preserve current remaining time-slice for the thread and clear the current time-slice. */ + temp_thread_ptr -> tx_thread_time_slice = _tx_timer_time_slice; + _tx_timer_time_slice = 0; + } + + /* Save the run semaphore into a temporary variable as well. */ + temp_run_semaphore = temp_thread_ptr -> tx_thread_win32_thread_run_semaphore; + + /* Pickup the current thread state. */ + temp_thread_state = temp_thread_ptr -> tx_thread_state; + + /* Setup the suspension type for this thread. */ + temp_thread_ptr -> tx_thread_win32_suspension_type = 0; + + /* Set the current thread pointer to NULL. */ + _tx_thread_current_ptr = TX_NULL; + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SYSTEM_RETURN-release_sem", __FILE__, __LINE__); + + /* Release the semaphore that the main scheduling thread is waiting + 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); + + /* Determine if the thread was self-terminating. */ + if (temp_thread_state == TX_TERMINATED) + { + + /* Exit the thread instead of waiting on the semaphore! */ + 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); + + /* 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); + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SYSTEM_RETURN-wake_up", __FILE__, __LINE__); + + /* Determine if the thread was terminated. */ + + /* Pickup the current thread pointer. */ + temp_thread_ptr = _tx_thread_current_ptr; + + /* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not + match the current thread pointer. */ + if ((threadpriority == THREAD_PRIORITY_LOWEST) && + ((!temp_thread_ptr) || (temp_thread_ptr -> tx_thread_win32_thread_id != threadid))) + { + + /* Leave Win32 critical section. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + + /* This indicates the Win32 thread was actually terminated by ThreadX and is only + being allowed to run in order to cleanup its resources. */ + ExitThread(0); + } + + /* Now determine if the application thread last had interrupts disabled. */ + + /* Debug entry. */ + _tx_win32_debug_entry_insert("SYSTEM_RETURN-finish", __FILE__, __LINE__); + + /* Determine if this thread had interrupts disabled. */ + if (!_tx_thread_current_ptr -> tx_thread_win32_int_disabled_flag) + { + + /* Leave Win32 critical section. */ + _tx_win32_critical_section_release(&_tx_win32_critical_section); + } +} + + diff --git a/ports/win64/vs_2022/src/tx_timer_interrupt.c b/ports/win64/vs_2022/src/tx_timer_interrupt.c new file mode 100644 index 00000000..6814334b --- /dev/null +++ b/ports/win64/vs_2022/src/tx_timer_interrupt.c @@ -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 Codex (gpt 5.4). + * 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 */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Win64/MSVC */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* 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 */ +/* _tx_win32_critical_section_obtain Obtain critical section */ +/* _tx_win32_critical_section_release Release critical section */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/**************************************************************************/ +VOID _tx_timer_interrupt(VOID) +{ + + + /* Enter critical section to ensure other threads are not playing with + the core ThreadX data structures. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + + /* Debug entry. */ + _tx_win32_debug_entry_insert("TIMER INTERRUPT", __FILE__, __LINE__); + + /* Increment the system clock. */ + _tx_timer_system_clock++; + + /* Test for time-slice expiration. */ + if (_tx_timer_time_slice) + { + + /* Decrement the time_slice. */ + _tx_timer_time_slice--; + + /* Check for expiration. */ + if (_tx_timer_time_slice == 0) + { + + /* Set the time-slice expired flag. */ + _tx_timer_expired_time_slice = TX_TRUE; + } + } + + /* Test for timer expiration. */ + if (*_tx_timer_current_ptr) + { + + /* Set expiration flag. */ + _tx_timer_expired = TX_TRUE; + } + else + { + + /* No timer expired, increment the timer pointer. */ + _tx_timer_current_ptr++; + + /* Check for wrap-around. */ + if (_tx_timer_current_ptr == _tx_timer_list_end) + { + + /* Wrap to beginning of list. */ + _tx_timer_current_ptr = _tx_timer_list_start; + } + } + + /* See if anything has expired. */ + if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + { + + /* Did a timer expire? */ + if (_tx_timer_expired) + { + + /* Process timer expiration. */ + _tx_timer_expiration_process(); + } + + /* Did time slice expire? */ + if (_tx_timer_expired_time_slice) + { + + /* Time slice interrupted thread. */ + _tx_thread_time_slice(); + } + } + + /* Exit Win32 critical section. */ + _tx_win32_critical_section_release(&_tx_win32_critical_section); +} + + diff --git a/ports/xtensa/xcc/example_build/demo_threadx.c b/ports/xtensa/xcc/example_build/demo_threadx.c index 72632323..0199a144 100644 --- a/ports/xtensa/xcc/example_build/demo_threadx.c +++ b/ports/xtensa/xcc/example_build/demo_threadx.c @@ -1,3 +1,14 @@ +/***************************************************************************/ +/* 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. */ diff --git a/ports/xtensa/xcc/inc/tx_port.h b/ports/xtensa/xcc/inc/tx_port.h index a8897815..5aeb58bf 100644 --- a/ports/xtensa/xcc/inc/tx_port.h +++ b/ports/xtensa/xcc/inc/tx_port.h @@ -340,7 +340,10 @@ typedef unsigned short USHORT; #define TX_THREAD_EXTENSION_2 /* Execution profile related */ -#define TX_THREAD_EXTENSION_3 +#define TX_THREAD_EXTENSION_3 \ + unsigned long long tx_thread_execution_time_total; \ + unsigned long tx_thread_execution_time_last_start; + /* Define the port extensions of the remaining ThreadX objects. */ @@ -458,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.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * Azure RTOS Xtensa Version 6.5.1.202602 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/xtensa/xcc/inc/xtensa_context.h b/ports/xtensa/xcc/inc/xtensa_context.h index 11174fff..2d06948b 100644 --- a/ports/xtensa/xcc/inc/xtensa_context.h +++ b/ports/xtensa/xcc/inc/xtensa_context.h @@ -373,19 +373,8 @@ XSTRUCT_END(XtExcFrame) #endif #endif - -/* -------------------------------------------------------------------------------- - This flag is meant for internal use. Have all interrupts be dispatched via a - common wrapper, which takes care of doing some OS-specific stuff common to - all interrupt handlers. Said stuff cannot safely be handled in the RTOS_ENTER - and RTOS_EXIT macros. -------------------------------------------------------------------------------- -*/ -#if (defined TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || (defined XT_INTEXC_HOOKS) -#define XT_USE_INT_WRAPPER 1 -#else -#define XT_USE_INT_WRAPPER 0 +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS > 32) && (defined XT_USE_SWPRI) +#error "Software prioritization of interrupts (XT_USE_SWPRI) not supported for XEA2 with > 32 interrupts." #endif #if XCHAL_HAVE_XEA3 @@ -500,12 +489,15 @@ XSTRUCT_END(XtExcFrame) #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY // Call the thread entry function to indicate the thread is executing. - // SP should be pointing to a safe region at this point. + // SP should be pointing to a safe region at this point. Note that a9 + // may be trashed by this call, must be reloaded. #ifdef __XTENSA_CALL0_ABI__ call0 _tx_execution_thread_enter #else call8 _tx_execution_thread_enter #endif + movi a9, _tx_thread_current_ptr // a9 <- &_tx_thread_current_ptr + l32i a9, a9, 0 // a9 <- _tx_thread_current_ptr #endif l32i a2, a9, tx_thread_solicited // a2 = solicited flag diff --git a/ports/xtensa/xcc/inc/xtensa_rtos.h b/ports/xtensa/xcc/inc/xtensa_rtos.h index d8db73bc..ef62035e 100644 --- a/ports/xtensa/xcc/inc/xtensa_rtos.h +++ b/ports/xtensa/xcc/inc/xtensa_rtos.h @@ -181,7 +181,11 @@ To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'. #define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI) #ifndef __ASSEMBLER__ +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS > 32) +typedef uint32_t (*XT_INTEXC_HOOK)(uint32_t cause, uint32_t block); +#else typedef uint32_t (*XT_INTEXC_HOOK)(uint32_t cause); +#endif extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM]; #endif diff --git a/ports/xtensa/xcc/inc/xtensa_timer.h b/ports/xtensa/xcc/inc/xtensa_timer.h index 957a42ed..fbbe4871 100644 --- a/ports/xtensa/xcc/inc/xtensa_timer.h +++ b/ports/xtensa/xcc/inc/xtensa_timer.h @@ -108,7 +108,19 @@ Otherwise select the first low or medium priority interrupt timer available. #define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM) #if XCHAL_HAVE_XEA2 -#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM) +/* + * Xtensa LX8 supports up to 128 interrupts whereas LX7 supports up to 32. + * + * Redefine the legacy XT_TIMER_INTEN (which limited the interrupt number to + * be in the lower 32 or lower 64 bits depending on data type) as two defines + * describing the INTEN bit within a 32-bit component and a 4-block component, + * where each block contains a group of 32 interrupt bits. + * + * Name changes are intentional such that any dependencies are caught at + * compile-time and are found regardless of timer configuration. + */ +#define XT_TIMER_INTEN_BIT (1 << (XT_TIMER_INTNUM & 31U)) +#define XT_TIMER_INTEN_BLK (XT_TIMER_INTNUM >> 5) #endif #if XT_TIMER_INDEX == 0 diff --git a/ports/xtensa/xcc/readme_threadx.txt b/ports/xtensa/xcc/readme_threadx.txt index 3ad4aec2..3f45c95f 100644 --- a/ports/xtensa/xcc/readme_threadx.txt +++ b/ports/xtensa/xcc/readme_threadx.txt @@ -22,7 +22,6 @@ processor configuration options: - Timer interrupt option with at least one interruptible timer for ThreadX. - Interrupt option (implied by the timer interrupt option). - Xtensa Exception Architecture 2 (XEA2) or Exception Architecture 3 (XEA3). - Please note that XEA1 is NOT supported. Minimal support for certain evaluation boards is provided via a board independent "XTBSP" API implemented by a board specific library. This @@ -35,143 +34,66 @@ this board support (a "raw" platform), but you will have to provide the clock frequency and drivers for any on-board devices you want to use. -2. Building the ThreadX run-time Library +2. Building the ThreadX Library and the Xtensa Example By default, you will build for the Xtensa instruction set simulator. If you have a supported emulation board, you can build to run on that. You -can also build to run on a raw Xtensa core with no "board support", a -good starting point for supporting your own target platform. Cadence Design Systems -recommends doing functional development on the simulator because it -is easier to debug with, then move to a board if/when you need to test -hardware drivers or real-time performance. +will have to provide the XTBSP functions for any other board you want to +run on. We recommend you start by running on the simulator, then moving +to your hardware target or emulation platform. -ThreadX/Xtensa comes with a Makefile as well as DOS .bat file, taking -advantage of xt-make, a version of GNU make that comes with Xtensa Tools -(you can just as well use generic GNU make if you have it installed). -The Makefile works on any host platform and provides for incremental builds. -The .bat file works on DOS/Windows only and always cleans before building. -The build for each target platform is placed in a sub-directory so several -platform builds can coexist even with incremental rebuilds. +ThreadX/Xtensa is built using the ThreadX Cmake infrastructure. See the +standard ThreadX documentation for details of the build process. In the +cmake/ directory there is a file named xtensa.cmake which defines the +Cmake configuration for the Xtensa target. Both Cmake and the Ninja tool +need to be installed to build ThreadX. -First, make sure you have installed Xtensa Tools and your processor -configuration, and be sure that Xtensa Tools are in your search path. +You will also need to ensure that the Xtensa SDK tools have been installed +and are on the path, and XTENSA_SYSTEM and XTENSA_CORE are set appropriately +in the environment. Refer to the SDK documentation for details. -If you wish to build for an evaluation board that is supported by an -external package, be sure the appropriate package is installed. See the -introduction (section 0) to determine if you need an external package. -If you are using an external board package, set the environment variable -XTENSA_BOARDS to the absolute path of the root of the installed support -package (or you can pass this to xt-make commands on the command line). -eg. XTENSA_BOARDS = C:\usr\xtensa\RB-2007.1-xtav60 for Avnet LX60 board. -You do not need to set XTENSA_BOARDS if using a Cadence Design Systems supported -board with Xtensa Tools RB-2007.2 and up (support is bundled with the tools). +The following commands will build the ThreadX library (some changes may be +required based on your setup) - -Next, change directories to the ThreadX installation directory, as follows: + cmake -S $(TX_SRCDIR) -B $(TX_BLDDIR) -DCMAKE_TOOLCHAIN_FILE=$(TX_SRCDIR)/cmake/xtensa.cmake -GNinja $(TX_SRCDIR) + cmake --build $(TX_BLDDIR) -> cd c:\threadx\xtensa\gnu +where TX_SRCDIR is the root of the ThreadX source tree, and TX_BLDDIR is +the location where you want the build output to go. -Now build the ThreadX library (tx.a) by executing the build_threadx.bat -batch file (or using the Makefile directly) while inside the threadx -directory, as follows: +Once the library is built, the Xtensa example can be built by going into +the directory ports/xtensa/xcc/example_build and running this command - -> build_threadx.bat +xt-clang -mlongcalls -Os -g -I../../../../common/inc -I../../../../common_smp/inc + -I../../../../ports/xtensa/xcc/inc -o demo_threadx.exe demo_threadx.c + ../../../../build/libthreadx.a -lxtutil -which always builds for the simulator (but you can edit it), or - -> xt-make - -which by default builds for the simulator (PLATFORM=sim), or either of - -> xt-make PLATFORM=board BOARD=<board> -or -> xt-make BOARD=<board> - -which builds for a specified supported board (note PLATFORM=board is -default when BOARD is defined). eg. BOARD=xtav60 for the Avnet LX60 -(XT-AV60) board. - -> xt-make PLATFORM=raw - -which builds for a raw Xtensa core with no "board support". - -> xt-make PLATFORM=gdbio - -Provides some very slow I/O support through the xt-gdb debugger. -For GDBIO to work, xt-gdb must remain connected to the target. - -If you are building for an Xtensa processor configuration that is not the -default you selected when you installed Xtensa Tools, you need to define the -environment variable XTENSA_CORE. If your configuration is not in the -default registry you selected when you installed Xtensa Tools, you also -need to define the environment variable XTENSA_SYSTEM. See tools manuals. -You can avoid defining these in your environment if you pass the variables -you need to redefine into xt-make as follows: - -> xt-make XTENSA_CORE=<your_config_name> XTENSA_SYSTEM=<your_registry> ... - -There are more details about build options in the comment in the Makefile. - -At this point, all the ThreadX objects are located in a library file: tx.a . -This file must be linked with your application in order to use ThreadX. -This library and all the intermediate object files are placed in a platform -specific sub-directory named the same as BOARD or PLATFORM (if BOARD is not -defined), for example "sim", "xtkc705". To build ThreadX with thread-safe C library support, define TX_THREAD_SAFE_CLIB -in your build, as described in section 5 and in the Makefile. Please note -that the C library is only safe for use in threads, not in interrupt handlers. -It may also safely be used in tx_application_define (after tx_kernel_enter, -before threads are running). - +to 1 (this is set by default in tx_port.h). Note that the C library is only +safe for use in threads, not in interrupt handlers. It may also safely be used +in tx_application_define (after tx_kernel_enter, before threads are running). -3. Demonstration System -The ThreadX demonstration is designed to execute under Xtensa instruction set -simulator (ISS) or on a supported evaluation board programmed with your Xtensa -processor configuration. +3. Running the Example -Building the demonstration is easy, simply execute the build_threadx_demo.bat -batch file while inside threadx directory, as follows: +The ThreadX Xtensa example is designed to be run on the Xtensa simulator (ISS) +or a hardware target. By default the example is built for the simulator target. +To run it, -> build_threadx_demo.bat + xt-run demo_threadx.exe or -> xt-make demo + xt-gdb demo_threadx.exe (if you want to run it under the debugger) -Be sure to set or pass into xt-make the variables described in section 2 above -for building the ThreadX library, including the PLATFORM or BOARD you want to -run on. - -This compiles demo_threadx.c (which is the demonstration application) and links -it with the ThreadX objects in tx.a. The resulting file demo_threadx.out is a -ELF binary file that can be downloaded and executed on the target. - -The demo binary appears in the platform specific sub-directory described earlier. -For the following commands, change to that directory or prepend it as the path -of demo_threadx.out. - - -To execute on the simulator: - -> xt-run [--turbo] demo_threadx.out - -The option --turbo provides much faster, but non-cycle-accurate simulation. -Refer to the Xtensa simulator user manual for further simulator options. - - -To execute on the simulator using the Xplorer GUI based debugger: - -> xplorer --debug demo_threadx.out - - -To execute on a supported evaluation board, download demo_threadx.out per -instructions in the tools manuals. Be sure the board has been programmed -with the correct configuration and is set up to boot from RAM and debug -a downloaded program! Optionally you may connect a terminal or terminal -emulator to the serial port on the board with settings as described in -the board user manual, and see the output of printf on the terminal (if -the demo was compiled with DEMO_USE_PRINTF or DEMO_USE_XTUTIL). +To execute on a supported hardware target, download the example to the board +following instructions in the SDK manuals. Make sure the board has been set +up with the correct configuration (if emulation board) and is set up to boot +from RAM and debug a downloaded program. Optionally you may connect a terminal +or terminal emulator to the serial port on the board with settings as described +in the board user manual, and see the output of printf on the terminal (if +the board support package supports directing standard output to the port). To obtain I/O on a "raw" platform such as an unsupported board, you need to provide low level I/O drivers (eg. inbyte() and outbyte() for character @@ -179,13 +101,8 @@ I/O if you want to use printf etc.). You can run "raw" executables on any Xtensa platform, including simulator and any board, but you will not see any behavior specific to the platform (eg. display, printed output, stopping simulation at end of program). You can, while debugging, use a -debugger mechanism called GDBIO to obtain basic I/O. Use PLATFORM=GDBIO -on your xt-make command line - this is the same as "raw" except it links -some stubs that communicate through the debugger. It is very slow! - -WARNING: It is tempting to add printf calls to other threads in the demo. -If you modify the code in any way, you may need adjust affected threads' -stack sizes. This is especially true if you add a printf call. See 4.5. +debugger mechanism called GDBIO to obtain basic I/O. This requires linking +with the gdbio support library. See the SDK documentation for details. 4. System Initialization @@ -272,16 +189,14 @@ are provided in tx_port.h assuming no optimization (default, -O0). Threads that call C library functions may need larger stacks than those that don't. In particular, use of printf requires a very large stack and will usually cause a stack overflow if inserted in a thread without -enlarging its stack size. See DEMO_STACK_SIZE_PRINTF in demo_threadx.c -for a guideline. Use printf with care! +enlarging its stack size. 5. Assembler / Compiler Switches The following are compiler switches used in building the ThreadX library -and demonstration system. These can be supplied by editing the Makefile -or by overriding the COPT or CFLAGS variables in the make command line -(eg. make COPT="-O2 -DTX_THREAD_SAFE_CLIB"). More details in Makefile. +and demonstration system. These can be supplied by editing the xtensa.cmake +file or by overriding from the environment or command line. Compiler Switch Meaning @@ -291,7 +206,6 @@ Compiler Switch Meaning -mlongcalls Allows assembler and linker to convert call instructions to longer indirect call sequences when target is out of range. - -x assembler-with-cpp Passes .s and .S files through C preprocessor. -Dmacro Define a preprocessor macro with no value. -Dmacro=value Define a preprocessor macro with a value. @@ -306,9 +220,6 @@ Application Defines (preprocessor macros definable with the -D option): can be customized in tx_application_define. Default off. - NOTE: Thread safe support for Xtensa C library requires Xtensa Tools - version RF-2015.2 or later. - TX_ENABLE_STACK_CHECKING Enable generic ThreadX support for stack overflow checking. This can help avoid long debugging sessions or customer support calls @@ -382,7 +293,8 @@ Application Defines (preprocessor macros definable with the -D option): higher bit numbers over those with lower bit numbers at the same level. This works only for low and medium priority interrupts that can be - dispatched to C handlers. + dispatched to C handlers on either NX cores or + on LX cores with 32 or fewer interrupts. TX_SYSTEM_STACK_SIZE=n Specify the size of the interrupt stack, which is the stack that all interrupt handlers switch @@ -455,7 +367,7 @@ If multiple threads use a register, the caller must save and restore it. The saved context stack frames for context switches that occur as a result of interrupt handling (interrupt frame) or from thread-level API calls -(solicited frame) are described in human readable form in xtensa_context.h . +(solicited frame) are described in human readable form in xtensa_context.h. All suspended threads have one of these two types of stack frames. The top of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the associated thread control block TX_THREAD. An Xtensa architecture port-specific diff --git a/ports/xtensa/xcc/src/tx_clib_lock.c b/ports/xtensa/xcc/src/tx_clib_lock.c index 9e308720..43f6e220 100644 --- a/ports/xtensa/xcc/src/tx_clib_lock.c +++ b/ports/xtensa/xcc/src/tx_clib_lock.c @@ -66,6 +66,8 @@ TX_MUTEX clib_lock_mutex; void __malloc_lock (struct _reent * ptr) { + (void) ptr; + if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) { return; } @@ -80,6 +82,8 @@ __malloc_lock (struct _reent * ptr) void __malloc_unlock (struct _reent * ptr) { + (void) ptr; + if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) { return; } @@ -99,6 +103,8 @@ __malloc_unlock (struct _reent * ptr) void __env_lock (struct _reent * ptr) { + (void) ptr; + if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) { return; } @@ -113,6 +119,8 @@ __env_lock (struct _reent * ptr) void __env_unlock (struct _reent * ptr) { + (void) ptr; + if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) { return; } @@ -128,6 +136,12 @@ __env_unlock (struct _reent * ptr) #include <errno.h> #include <sys/reent.h> +#if defined(__DYNAMIC_REENT__) +// Helps to keep code similar between dynamic and non-dynamic. +#undef _reent_ptr +struct _reent * _reent_ptr; +#endif + #define XT_NUM_CLIB_LOCKS (_MAX_LOCK + FOPEN_MAX) typedef TX_MUTEX * _Rmtx; @@ -201,6 +215,32 @@ _Mtxunlock (_Rmtx * mtx) #endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */ +#if defined(__DYNAMIC_REENT__) +/**************************************************************************/ +/* Return libc context pointer for current thread. Overrides weak */ +/* version in libc. Until real threads are active, use the libc's */ +/* global reent struct. */ +/**************************************************************************/ +struct _reent * +__getreent(void) +{ + TX_THREAD * thread_ptr = _tx_thread_current_ptr; + + if (thread_ptr) { + return &(thread_ptr->tx_thread_clib_reent); + } + +#if XSHAL_CLIB == XTHAL_CLIB_XCLIB + extern struct _reent g_reent; /* from xclib */ + return &g_reent; +#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB + extern struct _reent * _impure_ptr; /* from newlib */ + return _impure_ptr; +#else +#error "Unsupported C library for __DYNAMIC_REENT__" +#endif +} +#endif /**************************************************************************/ /* _sbrk_r - heap allocator. This function is called when the memory */ diff --git a/ports/xtensa/xcc/src/tx_initialize_low_level.c b/ports/xtensa/xcc/src/tx_initialize_low_level.c index de2c2b93..d52689cf 100644 --- a/ports/xtensa/xcc/src/tx_initialize_low_level.c +++ b/ports/xtensa/xcc/src/tx_initialize_low_level.c @@ -80,6 +80,8 @@ VOID _tx_initialize_low_level(VOID) /* Disable interrupts - don't want any that interact with ThreadX yet. */ TX_DISABLE + /* Suppress compiler warning about set but not used variable. */ + (void) interrupt_save; /* Disable stack limit checking if present. Whatever was set up earlier diff --git a/ports/xtensa/xcc/src/tx_thread_schedule.S b/ports/xtensa/xcc/src/tx_thread_schedule.S index 448dc6d7..6c595170 100644 --- a/ports/xtensa/xcc/src/tx_thread_schedule.S +++ b/ports/xtensa/xcc/src/tx_thread_schedule.S @@ -166,9 +166,18 @@ _tx_thread_schedule: #if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) /* Call the thread entry function to indicate the thread is executing. */ + /* Note a2 may be trashed by this call, must be reloaded. */ #ifdef __XTENSA_CALL0_ABI__ call0 _tx_execution_thread_enter + movi a2, _tx_thread_current_ptr + l32i a2, a2, 0 #else + /* Ensure that PS.WOE is set for windowed call */ + movi a0, PS_WOE + rsr.ps a3 + or a3, a3, a0 + wsr.ps a3 + rsync call8 _tx_execution_thread_enter #endif #endif @@ -229,14 +238,24 @@ _tx_thread_schedule: rsync /* ensure wsr.CPENABLE has completed */ #endif - wsr a3, PS /* no need to sync PS, delay is OK */ - - /* This does not return to its caller, but to the selected thread. */ + /* De-allocate the remainder of the frame before reenabling interrupts + * to avoid overrunning a task stack of TX_MINIMUM_STACK bytes, which + * can only handle one XT_STK_FRMSZ. + */ #ifdef __XTENSA_CALL0_ABI__ /* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */ /* the sp briefly point to an illegal stack location. Avoid that. */ - addi a2, sp, XT_STK_FRMSZ + addi a2, sp, XT_STK_FRMSZ /* fully deallocate stack frame */ mov sp, a2 + #else + addi a2, sp, XT_STK_FRMSZ - 48 /* initial SP at solicited entry; */ + movsp sp, a2 /* retw will deallocate remainder */ + #endif + + wsr a3, PS /* no need to sync PS, delay is OK */ + + /* This does not return to its caller, but to the selected thread. */ + #ifdef __XTENSA_CALL0_ABI__ ret #else retw diff --git a/ports/xtensa/xcc/src/tx_thread_system_return.S b/ports/xtensa/xcc/src/tx_thread_system_return.S index d1fc4a9f..af0fa24b 100644 --- a/ports/xtensa/xcc/src/tx_thread_system_return.S +++ b/ports/xtensa/xcc/src/tx_thread_system_return.S @@ -70,26 +70,25 @@ _tx_thread_system_return: Since this is solicited, no need to save regs compiler doesn't preserve. */ -#if XCHAL_HAVE_XEA3 #ifdef __XTENSA_CALL0_ABI__ - addi sp, sp, -16 + addi a2, sp, -16 /* avoid addi/addmi relaxation that */ + mov sp, a2 /* might temporarily move sp up */ #else entry sp, 48 #endif +#if XCHAL_HAVE_XEA3 s32i a0, sp, 0 /* save return address */ -#else - #ifdef __XTENSA_CALL0_ABI__ - addi a2, sp, -XT_STK_FRMSZ /* avoid addi/addmi relaxation that */ - mov sp, a2 /* might temporarily move sp up */ - #else - entry sp, XT_STK_FRMSZ - #endif #endif #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 __XTENSA_CALL0_ABI__ + /* Preserve a0 across the call. */ +#if !XCHAL_HAVE_XEA3 + s32i a0, sp, 0 +#endif call0 _tx_execution_thread_exit + l32i a0, sp, 0 #else call8 _tx_execution_thread_exit #endif @@ -109,6 +108,7 @@ _tx_thread_system_return: interrupts enabled, but we will have to revert SP to point above the exception frame because that is what the dispatch code expects. Must disable interrupts before that. + TODO: disable interrupts prior to stack allocation as we do for XEA2 */ movi a0, .Lret @@ -185,7 +185,27 @@ _tx_thread_system_return: #else /* XEA1 or XEA2 */ + /* Disable interrupts before allocating the full stack frame. Taking + * an interrupt will allocate a second exception stack frame, which will + * overrun a task stack of TX_MINIMUM_STACK bytes. + * Read PS so it can be saved off after stack adjustment. + */ rsr a2, PS + XT_INTS_DISABLE(a3) + + /* Allocate the remainder of the frame here; we already allocated + * 16 bytes for call0 or 48 bytes for windowed upon entry. + * This memory will be deallocated in the solicited exit logic prior + * to reenabling interrupts. + */ + #ifdef __XTENSA_CALL0_ABI__ + addi a3, sp, -XT_STK_FRMSZ + 16 // avoid addi/addmi relaxation again + mov sp, a3 + #else + addi a3, sp, -XT_STK_FRMSZ + 48 + movsp sp, a3 + #endif + s32i a0, sp, XT_STK_PC s32i a2, sp, XT_STK_PS #ifdef __XTENSA_CALL0_ABI__ @@ -205,8 +225,6 @@ _tx_thread_system_return: wsr a2, PS rsync call0 xthal_window_spill_nw - l32i a0, sp, XT_STK_PS - wsr a0, PS // Restore PS value rsync #endif @@ -226,10 +244,9 @@ _tx_thread_system_return: a4 = &_tx_timer_time_slice */ - /* Lock out interrupts (except hi-pri). */ + /* Already locked out interrupts (except hi-pri). */ /* Grab thread control block of current thread. */ movi a2, _tx_thread_current_ptr /* a2 = &_tx_thread_current_ptr */ - XT_INTS_DISABLE(a0) l32i a3, a2, 0 /* a3 points to TCB */ /* Mark as having solicited entry to kernel (used on exit). */ diff --git a/ports/xtensa/xcc/src/xtensa_context.S b/ports/xtensa/xcc/src/xtensa_context.S index e4b9aa0a..7e58ba14 100644 --- a/ports/xtensa/xcc/src/xtensa_context.S +++ b/ports/xtensa/xcc/src/xtensa_context.S @@ -131,7 +131,7 @@ _xt_context_save: s32i a3, sp, XT_STK_ATOMCTL #endif - #if XT_USE_SWPRI + #ifdef XT_USE_SWPRI /* Save virtual priority mask */ movi a3, _xt_vpri_mask l32i a3, a3, 0 @@ -318,7 +318,7 @@ _xt_context_restore: ret -#endif /* XCHAL_HAVE_XEA3 */ +#endif /* XCHAL_HAVE_XEA2 */ /******************************************************************************* diff --git a/ports/xtensa/xcc/src/xtensa_intr.c b/ports/xtensa/xcc/src/xtensa_intr.c index c5f320cb..2f0622cd 100644 --- a/ports/xtensa/xcc/src/xtensa_intr.c +++ b/ports/xtensa/xcc/src/xtensa_intr.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2006-2019 Cadence Design Systems Inc. +Copyright (c) 2006-2023 Cadence Design Systems Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -80,7 +80,7 @@ xt_exc_handler xt_set_exception_handler(uint32_t n, xt_exc_handler f) #if XCHAL_HAVE_INTERRUPTS -#if XCHAL_HAVE_XEA2 +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32) /* Defined in xtensa_intr_asm.S */ extern uint32_t _xt_intenable; extern uint32_t _xt_vpri_mask; @@ -93,7 +93,7 @@ typedef struct xt_handler_table_entry { void * arg; } xt_handler_table_entry; -#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3) +#if XCHAL_HAVE_XEA3 extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1]; #else extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; @@ -131,7 +131,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg) } #endif -#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3) +#if XCHAL_HAVE_XEA3 entry = _xt_interrupt_table + n + 1; #else entry = _xt_interrupt_table + n; @@ -157,7 +157,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg) */ void xt_interrupt_enable(uint32_t intnum) { -#if XCHAL_HAVE_XEA2 +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32) uint32_t ps = XT_RSIL(15); // New INTENABLE = (_xt_intenable | mask) & _xt_vpri_mask. @@ -177,7 +177,7 @@ void xt_interrupt_enable(uint32_t intnum) */ void xt_interrupt_disable(uint32_t intnum) { -#if XCHAL_HAVE_XEA2 +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32) uint32_t ps = XT_RSIL(15); // New INTENABLE = (_xt_intenable & ~mask) & _xt_vpri_mask. diff --git a/ports/xtensa/xcc/src/xtensa_intr_asm.S b/ports/xtensa/xcc/src/xtensa_intr_asm.S index e972378a..c2bf1574 100644 --- a/ports/xtensa/xcc/src/xtensa_intr_asm.S +++ b/ports/xtensa/xcc/src/xtensa_intr_asm.S @@ -45,7 +45,7 @@ ------------------------------------------------------------------------------- */ -#if XCHAL_HAVE_XEA2 +#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32) .data .global _xt_intdata @@ -112,9 +112,6 @@ _xt_interrupt_table: #if XCHAL_HAVE_XEA3 .word xt_interrupt_wrapper .word 0 -#elif XT_USE_INT_WRAPPER - .word 0 - .word 0 #endif .set i, 0 diff --git a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c index 4ccb29f5..76efec68 100644 --- a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c +++ b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c @@ -40,7 +40,7 @@ #include "tx_thread.h" #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY -#include "tx_execution_profile.h" +#include "../../utility/execution_profile_kit/tx_execution_profile.h" #endif diff --git a/ports/xtensa/xcc/src/xtensa_vectors.S b/ports/xtensa/xcc/src/xtensa_vectors.S index 7b09638e..1dedd83d 100644 --- a/ports/xtensa/xcc/src/xtensa_vectors.S +++ b/ports/xtensa/xcc/src/xtensa_vectors.S @@ -75,6 +75,12 @@ /* Enable stack backtrace across exception/interrupt - see below */ #define XT_DEBUG_BACKTRACE 1 +#if (XCHAL_NUM_INTERRUPTS > 32) +#define XT_EXTD_INTERRUPTS 1 +#else +#define XT_EXTD_INTERRUPTS 0 +#endif + /* -------------------------------------------------------------------------------- @@ -103,6 +109,97 @@ addi \aout, \aout, 1 /* return aout + 1 */ .endm + +/* +-------------------------------------------------------------------------------- + Macro debug_backtrace + + This bit of code provides a nice debug backtrace in the debugger. + It does take a few more instructions, so undef XT_DEBUG_BACKTRACE + if you want to save the cycles. + + Input : "ra" - Return address register (clobbered) + Input : "tmp" - Temp register (clobbered), must be a different register + Input : "level" - Numeric interrupt level + Output : "ra" - Return address modified to simulate call4 +-------------------------------------------------------------------------------- +*/ + + .macro debug_backtrace ra, tmp, level + #if XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr \ra, EPC_1 + \level - 1 /* return address */ + movi \tmp, 0xC0000000 /* constant with top 2 bits set (call size) */ + or \ra, \ra, \tmp /* set top 2 bits */ + addx2 \ra, \tmp, \ra /* clear top bit -- simulating call4 size */ + #endif + #endif + .endm + + +/* +-------------------------------------------------------------------------------- + Macro call_exec_isr_entry_fn + + Call the ISR enter function to indicate an ISR is executing. + + Inputs : None + Output : Nothing +-------------------------------------------------------------------------------- +*/ + .macro call_exec_isr_entry_fn + #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + #ifdef __XTENSA_CALL0_ABI__ + /* Preserve a2 across the call, a12 is callee-saved for call0 ABI. */ + mov a12, a2 + call0 _tx_execution_isr_enter + mov a2, a12 + #else + call4 _tx_execution_isr_enter + #endif + #endif + .endm + + +/* +-------------------------------------------------------------------------------- + Macro call_int_hook + + Call interrupt hook if present to (pre)handle interrupts. + NOTE: macro does not parameterize all used registers since they cannot freely + be changed, either due to ABI conventions or other assembly code in this file. + + Input : "level" - Interrupt level being processed + Input : "block" - Index of interrupt block being processed [0..3] + Input : "goto_on_done" - Label where control proceeds to if hook returns 0 + Input : a2 - bitmask of pending interrupts in block being processed [0..3] + Output : a2 - updated bitmask of pending interrupts + Clobbers : a2, a4, and: + Clobbers : for windowed ABI: a6, a7 + Clobbers : for call0 ABI: a3 +-------------------------------------------------------------------------------- +*/ + .macro call_int_hook level, block, goto_on_done + #ifdef XT_INTEXC_HOOKS + movi a4, _xt_intexc_hooks + l32i a4, a4, \level << 2 + beqz a4, 2f + #ifdef __XTENSA_CALL0_ABI__ + movi a3, \block + callx0 a4 + beqz a2, \goto_on_done + #else + mov a6, a2 + movi a7, \block + callx4 a4 + beqz a6, \goto_on_done + mov a2, a6 + #endif +2: + #endif + .endm + + /* -------------------------------------------------------------------------------- Macro dispatch_c_isr - dispatch interrupts to user ISRs. @@ -124,59 +221,134 @@ NOTE: This macro will use registers a0 and a2-a6. The arguments are: level -- interrupt level mask -- interrupt bitmask for this level + mask1 -- interrupt bitmask for this level for bits 63:32 (XT_EXTD_INTERRUPTS) + mask2 -- interrupt bitmask for this level for bits 95:64 (XT_EXTD_INTERRUPTS) + mask3 -- interrupt bitmask for this level for bits 127:96 (XT_EXTD_INTERRUPTS) -------------------------------------------------------------------------------- */ - .macro dispatch_c_isr level mask + .macro dispatch_c_isr level mask mask1 mask2 mask3 /* Get mask of pending, enabled interrupts at this level into a2. */ .L_xt_user_int_&level&: - rsr a2, INTENABLE + + #if XT_EXTD_INTERRUPTS + + /* When > 32 interrupts are configured, maintain at least 2 instructions + between RSR.INTERRUPT and branch instructions to avoid interlocks. + */ + #if (XCHAL_NUM_INTERRUPTS > 96) + rsr a6, INTERRUPT3 + #endif + #if (XCHAL_NUM_INTERRUPTS > 64) + rsr a5, INTERRUPT2 + #endif + rsr a4, INTERRUPT1 rsr a3, INTERRUPT - movi a4, \mask - and a2, a2, a3 - and a2, a2, a4 - beqz a2, 9f /* nothing to do */ + #if (XCHAL_NUM_INTERRUPTS > 96) + _bnez a6, .L_xt_user_int_&level&_chk_blk3 + #endif + #if (XCHAL_NUM_INTERRUPTS > 64) + _bnez a5, .L_xt_user_int_&level&_chk_blk2 + #endif + _bnez a4, .L_xt_user_int_&level&_chk_blk1 + _bnez a3, .L_xt_user_int_&level&_chk + j 9f /* spurious */ - /* This bit of code provides a nice debug backtrace in the debugger. - It does take a few more instructions, so undef XT_DEBUG_BACKTRACE - if you want to save the cycles. + #if (XCHAL_NUM_INTERRUPTS > 96) + /* Identify and process block 3 interrupts. If none are active, + proceed to check subsequent blocks; thus preserve a3-a5. */ - #if XT_DEBUG_BACKTRACE - #ifndef __XTENSA_CALL0_ABI__ - rsr a0, EPC_1 + \level - 1 /* return address */ - movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ - or a0, a0, a4 /* set top 2 bits */ - addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ +.L_xt_user_int_&level&_chk_blk3: + rsr a2, INTENABLE3 + and a2, a2, a6 + movi a6, \mask3 + and a2, a2, a6 + beqz a2, .L_xt_user_int_&level&_chk_blk2 + + /* Block 3 interrupt(s) pending */ + debug_backtrace a0, a4, \level + call_exec_isr_entry_fn + call_int_hook \level, 3, 9f + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + wsr a4, INTCLEAR3 /* clear sw or edge-triggered interrupt */ + #ifndef TX_NO_TIMER + #if (XT_TIMER_INTEN_BLK == 3) + movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */ + beq a3, a4, 7f /* if timer interrupt then skip table */ #endif #endif + movi a5, _xt_interrupt_table + 8*96 /* a5 = dispatch table for block 3 */ + j .L_xt_user_int_&level&_post_clear + #endif - #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY - /* Call the ISR enter function to indicate an ISR is executing. */ - #ifdef __XTENSA_CALL0_ABI__ - call0 _tx_execution_isr_enter - #else - call4 _tx_execution_isr_enter + #if (XCHAL_NUM_INTERRUPTS > 64) + /* Identify and process block 2 interrupts. If none are active, + proceed to check subsequent blocks; thus preserve a3-a4. + */ +.L_xt_user_int_&level&_chk_blk2: + rsr a2, INTENABLE2 + movi a6, \mask2 + and a2, a2, a5 + and a2, a2, a6 + beqz a2, .L_xt_user_int_&level&_chk_blk1 + + /* Block 2 interrupt(s) pending */ + debug_backtrace a0, a4, \level + call_exec_isr_entry_fn + call_int_hook \level, 2, 9f + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + wsr a4, INTCLEAR2 /* clear sw or edge-triggered interrupt */ + #ifndef TX_NO_TIMER + #if (XT_TIMER_INTEN_BLK == 2) + movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */ + beq a3, a4, 7f /* if timer interrupt then skip table */ + #endif #endif + movi a5, _xt_interrupt_table + 8*64 /* a5 = dispatch table for block 2 */ + j .L_xt_user_int_&level&_post_clear #endif - #ifdef XT_INTEXC_HOOKS - /* Call interrupt hook if present to (pre)handle interrupts. */ - movi a4, _xt_intexc_hooks - l32i a4, a4, \level << 2 - beqz a4, 2f - #ifdef __XTENSA_CALL0_ABI__ - callx0 a4 - beqz a2, 9f - #else - mov a6, a2 - callx4 a4 - beqz a6, 9f - mov a2, a6 + /* Identify and process block 1 interrupts. If none are active, + proceed to check subsequent blocks; thus preserve a3. + */ +.L_xt_user_int_&level&_chk_blk1: + rsr a2, INTENABLE1 + movi a6, \mask1 + and a2, a2, a4 + and a2, a2, a6 + beqz a2, .L_xt_user_int_&level&_chk + + /* Block 1 interrupt(s) pending */ + debug_backtrace a0, a4, \level + call_exec_isr_entry_fn + call_int_hook \level, 1, 9f + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + wsr a4, INTCLEAR1 /* clear sw or edge-triggered interrupt */ + #ifndef TX_NO_TIMER + #if (XT_TIMER_INTEN_BLK == 1) + movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */ + beq a3, a4, 7f /* if timer interrupt then skip table */ #endif -2: #endif + movi a5, _xt_interrupt_table + 8*32 /* a5 = dispatch table for block 1 */ + j .L_xt_user_int_&level&_post_clear + + #else /* !XT_EXTD_INTERRUPTS */ + rsr a3, INTERRUPT + #endif + +.L_xt_user_int_&level&_chk: + rsr a2, INTENABLE + movi a4, \mask + and a2, a2, a3 + and a2, a2, a4 + beqz a2, 9f /* nothing to do */ + + debug_backtrace a0, a4, \level + call_exec_isr_entry_fn + call_int_hook \level, 0, 9f /* Now look up in the dispatch table and call user ISR if any. */ /* If multiple bits are set then MSB has highest priority. */ @@ -186,7 +358,7 @@ #ifdef XT_USE_SWPRI /* Enable all interrupts at this level that are numerically higher than the one we just selected, since they are treated as higher - priority. + priority. NOTE: SWPRI disabled for XT_EXTD_INTERRUPTS. */ movi a3, \mask /* a3 = all interrupts at this level */ add a2, a4, a4 /* a2 = a4 << 1 */ @@ -205,33 +377,42 @@ #endif wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ - #ifndef TX_NO_TIMER - movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ + #if (XT_TIMER_INTEN_BLK == 0) + movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */ beq a3, a4, 7f /* if timer interrupt then skip table */ #endif + #endif + movi a5, _xt_interrupt_table + /* Execution could arrive here from the direct, <= 32 interrupt case, or + from one of the XT_EXTD_INTERRUPTS blocks. Regardless, we have: + a4 = MSB (of 32-bit block) of pending interrupt bits, already cleared + a5 = Base of interrupt table (of 32-bit block) + */ +.L_xt_user_int_&level&_post_clear: find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ - movi a4, _xt_interrupt_table - addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ + addx8 a3, a3, a5 /* a3 = address of interrupt table entry */ l32i a4, a3, XIE_HANDLER /* a4 = handler address */ #ifdef __XTENSA_CALL0_ABI__ + #ifdef XT_USE_SWPRI mov a12, a6 /* save in callee-saved reg */ + #endif l32i a2, a3, XIE_ARG /* a2 = handler arg */ callx0 a4 /* call handler */ + #ifdef XT_USE_SWPRI mov a2, a12 - #else + #endif + #else /* !__XTENSA_CALL0_ABI__ */ + #ifdef XT_USE_SWPRI mov a2, a6 /* save in windowed reg */ + #endif l32i a6, a3, XIE_ARG /* a6 = handler arg */ callx4 a4 /* call handler */ #endif - #ifdef XT_USE_SWPRI j 8f - #else - j .L_xt_user_int_&level& /* check for more interrupts */ - #endif 7: @@ -245,24 +426,24 @@ */ #ifdef __XTENSA_CALL0_ABI__ + #ifdef XT_USE_SWPRI mov a12, a6 + #endif call0 XT_RTOS_TIMER_INT + #ifdef XT_USE_SWPRI mov a2, a12 + #endif #else + #ifdef XT_USE_SWPRI mov a2, a6 + #endif call4 XT_RTOS_TIMER_INT #endif .endif #endif - #ifdef XT_USE_SWPRI - j 8f - #else - j .L_xt_user_int_&level& /* check for more interrupts */ - #endif - - #ifdef XT_USE_SWPRI 8: + #ifdef XT_USE_SWPRI /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from virtual _xt_intenable which _could_ have changed during interrupt @@ -275,7 +456,17 @@ s32i a2, a3, 4 /* update _xt_vpri_mask */ and a4, a4, a2 /* a4 = masked intenable */ wsr a4, INTENABLE /* update INTENABLE */ - #endif + + #elif XT_EXTD_INTERRUPTS + + rsr a2, INTPBL /* INTPBL bit(n-1): pending Ln interrupt */ + bbsi.l a2, \level - 1, .L_xt_user_int_&level& + + #else + + j .L_xt_user_int_&level& /* check for more interrupts */ + + #endif /* XT_USE_SWPRI */ 9: /* done */ @@ -769,7 +960,11 @@ _xt_lowint1: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK XCHAL_INTLEVEL1_MASK1 XCHAL_INTLEVEL1_MASK2 XCHAL_INTLEVEL1_MASK3 +#else dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -849,7 +1044,11 @@ _xt_medint2: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK XCHAL_INTLEVEL2_MASK1 XCHAL_INTLEVEL2_MASK2 XCHAL_INTLEVEL2_MASK3 +#else dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -920,7 +1119,11 @@ _xt_medint3: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK XCHAL_INTLEVEL3_MASK1 XCHAL_INTLEVEL3_MASK2 XCHAL_INTLEVEL3_MASK3 +#else dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -990,7 +1193,11 @@ _xt_medint4: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK XCHAL_INTLEVEL4_MASK1 XCHAL_INTLEVEL4_MASK2 XCHAL_INTLEVEL4_MASK3 +#else dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -1060,7 +1267,11 @@ _xt_medint5: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK XCHAL_INTLEVEL5_MASK1 XCHAL_INTLEVEL5_MASK2 XCHAL_INTLEVEL5_MASK3 +#else dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ @@ -1130,7 +1341,11 @@ _xt_medint6: /* OK to call C code at this point, dispatch user ISRs */ +#if XT_EXTD_INTERRUPTS + dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK XCHAL_INTLEVEL6_MASK1 XCHAL_INTLEVEL6_MASK2 XCHAL_INTLEVEL6_MASK3 +#else dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK +#endif /* Done handling interrupts, transfer control to OS */ call0 XT_RTOS_INT_EXIT /* does not return directly here */ |
