diff options
Diffstat (limited to 'ports_smp')
344 files changed, 7381 insertions, 5555 deletions
diff --git a/ports_smp/arc_hs_smp/metaware/inc/tx_port.h b/ports_smp/arc_hs_smp/metaware/inc/tx_port.h index 8b084160..335ec252 100644 --- a/ports_smp/arc_hs_smp/metaware/inc/tx_port.h +++ b/ports_smp/arc_hs_smp/metaware/inc/tx_port.h @@ -395,7 +395,7 @@ typedef struct TX_THREAD_SMP_PROTECT_STRUCT #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/ARC_HS/MetaWare Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/ARC_HS/MetaWare Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s index 6014bdb2..13562cc8 100644 --- a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s +++ b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -187,10 +189,19 @@ __tx_thread_not_nested_save: ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; ; st sp, [r1, 8] ; Save thread's stack pointer +; +; /* Switch to the system stack. */ +; sp = _tx_thread_system_stack_ptr[core]; +; + mov r1, _tx_thread_system_stack_ptr ; Build address of system stack pointer + add r1, r1, r3 ; + ld sp, [r1] ; Switch to system stack .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY ; -; /* Call the ISR enter function to indicate an ISR is executing. */ +; /* Call the ISR enter function to indicate an ISR is executing. The call is +; made after the switch to the system stack so that it does not consume any +; of the interrupted thread's stack. */ ; sub sp, sp, 32 ; Allocating some space on the stack st blink, [sp, 16] ; Save blink @@ -199,14 +210,8 @@ __tx_thread_not_nested_save: ld blink, [sp, 16] ; Recover blink add sp, sp, 32 ; Recover the stack space .endif -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; -; - mov r1, _tx_thread_system_stack_ptr ; Build address of system stack pointer - add r1, r1, r3 ; - j_s.d [blink] ; Return to calling ISR - ld sp, [r1] ; Switch to system stack + + j_s [blink] ; Return to calling ISR ; ; } ; else diff --git a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/.cproject b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/.cproject index dccae911..39ba5656 100644 --- a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/.cproject +++ b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/.cproject @@ -29,7 +29,7 @@ <toolChain id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.base.var.arm_compiler_6-6"> - <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1337922098" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="cortex-a34.AArch64.ARMv8.Neon.Crypto" valueType="string"/> + <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1337922098" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A34.AArch64.ARMv8.Neon.Crypto" valueType="string"/> <targetPlatform id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597.2060144338" name=""/> diff --git a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 9aefbdcd..3cbf2cc1 100644 --- a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -6,17 +6,17 @@ <stringAttribute key="ANDROID_PROCESS_NAME" value=""/> <mapAttribute key="AverageDurationTracker"> <mapEntry key="*Fetching Data" value="34126331"/> - <mapEntry key="*Fetching Data Model" value="1439173"/> + <mapEntry key="*Fetching Data Model" value="1887986"/> <mapEntry key="*FunctionLoader" value="137168653"/> - <mapEntry key="*list global low level symbols" value="2707112"/> + <mapEntry key="*list global low level symbols" value="3163826"/> <mapEntry key="*loading memory from target" value="2367919"/> - <mapEntry key="*loading values from target" value="8477514"/> + <mapEntry key="*loading values from target" value="8665557"/> <mapEntry key="*trace" value="1527238"/> - <mapEntry key="*updating expressions" value="101886453"/> + <mapEntry key="*updating expressions" value="25251903"/> <mapEntry key="*updating local_variables" value="836905"/> <mapEntry key="*updating registers" value="97090462"/> <mapEntry key="*updating variables" value="877039"/> - <mapEntry key="AddEventObserver" value="6587743"/> + <mapEntry key="AddEventObserver" value="5292071"/> <mapEntry key="Evaluate" value="1689813"/> <mapEntry key="ResumeToHere" value="20159012"/> <mapEntry key="Retrieving globals list" value="21298708"/> @@ -24,11 +24,11 @@ <mapEntry key="backtrace" value="21505977"/> <mapEntry key="break" value="9764564"/> <mapEntry key="checking tracepoints" value="372731"/> - <mapEntry key="compute execution mode" value="557345"/> + <mapEntry key="compute execution mode" value="835755"/> <mapEntry key="console" value="11946310"/> - <mapEntry key="continue" value="12697403"/> + <mapEntry key="continue" value="21247618"/> <mapEntry key="core" value="5451456"/> - <mapEntry key="directory" value="4737162"/> + <mapEntry key="directory" value="4479981"/> <mapEntry key="disable" value="2444670"/> <mapEntry key="disassemble" value="64135505"/> <mapEntry key="enable" value="5445745"/> @@ -36,40 +36,41 @@ <mapEntry key="evaluate address" value="1056014"/> <mapEntry key="finish" value="20115248"/> <mapEntry key="get byte order" value="633302"/> - <mapEntry key="get capabilities" value="548556"/> - <mapEntry key="get execution addresss" value="438164"/> - <mapEntry key="get source lines" value="3151194"/> - <mapEntry key="get substitute paths" value="293110"/> + <mapEntry key="get capabilities" value="382078"/> + <mapEntry key="get execution addresss" value="403253"/> + <mapEntry key="get source lines" value="951928"/> + <mapEntry key="get substitute paths" value="523052"/> <mapEntry key="getValidEncodings" value="1202320"/> - <mapEntry key="initialize command help" value="68196070"/> + <mapEntry key="initialize command help" value="63855085"/> <mapEntry key="interrupt" value="11210435"/> - <mapEntry key="list breakpoint options" value="1264804"/> - <mapEntry key="list breakpoints" value="1473749"/> - <mapEntry key="list instruction sets" value="1512051"/> - <mapEntry key="list signals" value="1314040"/> + <mapEntry key="list breakpoint options" value="2030851"/> + <mapEntry key="list breakpoints" value="1627224"/> + <mapEntry key="list instruction sets" value="1847125"/> + <mapEntry key="list signals" value="1953020"/> <mapEntry key="list source files" value="573423"/> - <mapEntry key="list watchpoint options" value="4130737"/> - <mapEntry key="list watchpoints" value="739118"/> - <mapEntry key="loadfile" value="308178719"/> + <mapEntry key="list watchpoint options" value="6057468"/> + <mapEntry key="list watchpoints" value="970059"/> + <mapEntry key="loadfile" value="386648009"/> <mapEntry key="next" value="24266800"/> <mapEntry key="query supports threads" value="215433"/> - <mapEntry key="remove" value="3597385"/> - <mapEntry key="run script" value="37326822"/> - <mapEntry key="set CWD" value="4366642"/> + <mapEntry key="remove" value="7663692"/> + <mapEntry key="run script" value="44460661"/> + <mapEntry key="set CWD" value="5180571"/> <mapEntry key="set breakpoint properties" value="10666013"/> - <mapEntry key="set debug-from" value="1215725"/> - <mapEntry key="set substitute-path" value="23083827"/> - <mapEntry key="source use_model_semihosting.ds" value="7540462"/> - <mapEntry key="start" value="36728254"/> + <mapEntry key="set debug-from" value="1157012"/> + <mapEntry key="set substitute-path" value="27245163"/> + <mapEntry key="source use_model_semihosting.ds" value="8849881"/> + <mapEntry key="start" value="50528177"/> <mapEntry key="step" value="26461127"/> <mapEntry key="stepi" value="29574773"/> <mapEntry key="synchronizing trace ranges" value="21582"/> <mapEntry key="target reset" value="32992642"/> - <mapEntry key="toggleBreakpoint" value="7875634"/> + <mapEntry key="toggleBreakpoint" value="19462208"/> <mapEntry key="updateBreakpointLocation" value="1868000"/> - <mapEntry key="waitForTargetToStop" value="47515299"/> + <mapEntry key="waitForTargetToStop" value="52570549"/> <mapEntry key="write expression" value="21220700"/> </mapAttribute> + <stringAttribute key="CLOCK_SPEED" value="Auto"/> <listAttribute key="DEBUG_TAB."/> <stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/> <stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx}"/> @@ -89,15 +90,15 @@ <stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.VALUE" value=""/> <intAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.COUNT" value="1"/> <listAttribute key="FILES.DEBUG_RESIDENT_APP"/> - <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="APPLICATION_ON_TARGET"/> <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.VALUE" value=""/> - <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="APPLICATION_ON_TARGET"/> + <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.VALUE" value=""/> <intAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.COUNT" value="2"/> <listAttribute key="FILES.DOWNLOAD_AND_DEBUG"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/> @@ -105,13 +106,13 @@ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.VALUE" value=""/> <intAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.COUNT" value="3"/> <listAttribute key="FILES.DOWNLOAD_DEBUG"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/> @@ -119,7 +120,7 @@ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.VALUE" value=""/> <intAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.COUNT" value="3"/> <intAttribute key="FILES.DOWNLOAD_DEBUG_ANDROID.RESOURCES.COUNT" value="0"/> @@ -162,6 +163,8 @@ <intAttribute key="POST_TRIGGER_CAPTURE_SIZE" value="50"/> <booleanAttribute key="RSE_USE_HOSTNAME" value="true"/> <booleanAttribute key="STOP_ON_TRIGGER" value="false"/> + <booleanAttribute key="SWD" value="false"/> + <booleanAttribute key="SWJ" value="true"/> <stringAttribute key="TCP_DISABLE_EXTENDED_MODE" value="true"/> <booleanAttribute key="TCP_KILL_ON_EXIT" value="false"/> <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.ExpressionsView"> @@ -211,13 +214,6 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -313,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A34x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> - <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A35x4"/> + <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A34x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a34x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -363,7 +359,7 @@ <mapEntry key="6" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/> <mapEntry key="7" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/> </mapAttribute> - <stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	187	-1	true	1	false	true	90	-1	true	2	true	true	108	-1	true	3	true	true	57	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	148	-1	true	7	true	true	53	-1	true"/> + <stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	255	-1	true	1	false	true	127	-1	true	2	true	true	159	-1	true	3	true	true	75	-1	true	4	true	true	65	-1	true	5	true	true	48	-1	true	6	true	true	241	-1	true	7	true	true	69	-1	true"/> <stringAttribute key="debugger.view.MemoryView" value="<?xml version="1.0" encoding="UTF-8"?> <page> 	<memoryView/> </page> "/> <listAttribute key="debugger.view.MemoryView:current"> <listEntry value=""/> @@ -386,24 +382,16 @@ <stringAttribute key="dtsl_options_file" value="default"/> <stringAttribute key="dtsl_tracecapture_option" value="options.trace.traceCapture"/> <booleanAttribute key="linuxOS" value="false"/> - <stringAttribute key="model_connection_address" value=""/> + <stringAttribute key="model_connection_address" value="127.0.0.1:7100"/> <stringAttribute key="model_iris" value="1"/> <stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/> <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> - <listEntry value=""FVP_Base_Cortex-A35x4""/> + <listEntry value=""FVP_Base_Cortex-A34x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a34_smp/ac6/example_build/tx/.cproject b/ports_smp/cortex_a34_smp/ac6/example_build/tx/.cproject index 742b0fa7..0b74b41a 100644 --- a/ports_smp/cortex_a34_smp/ac6/example_build/tx/.cproject +++ b/ports_smp/cortex_a34_smp/ac6/example_build/tx/.cproject @@ -7,7 +7,19 @@ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944" moduleId="org.eclipse.cdt.core.settings" name="Debug"> - <externalSettings/> + <externalSettings> + + <externalSetting> + + <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/tx"/> + + <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/tx/Debug"/> + + <entry flags="RESOLVED" kind="libraryFile" name="tx" srcPrefixMapping="" srcRootPath=""/> + + </externalSetting> + + </externalSettings> <extensions> @@ -29,7 +41,7 @@ <toolChain id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1684503312" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6"> - <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.982423385" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="cortex-a34.AArch64.ARMv8.Neon.Crypto" valueType="string"/> + <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.982423385" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A34.AArch64.ARMv8.Neon.Crypto" valueType="string"/> <targetPlatform id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1684503312.2127819066" name=""/> @@ -105,9 +117,25 @@ </folderInfo> + <fileInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944.214318543" name="tx_thread_timeout.c" rcbsApplicability="disable" resourcePath="src_generic/tx_thread_timeout.c" toolsToInvoke="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1899536638"> + + <tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1899536638" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428"> + + <inputType id="com.arm.tool.c.compiler.v6.base.input.1006773355" superClass="com.arm.tool.c.compiler.v6.base.input"/> + + </tool> + + </fileInfo> + + <fileInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944.1145515026" name="tx_misra.c" rcbsApplicability="disable" resourcePath="src_generic/tx_misra.c" toolsToInvoke="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1242981128"> + + <tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1242981128" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428"/> + + </fileInfo> + <sourceEntries> - <entry excluding="src_generic/tx_misra.c|src_generic/tx_thread_timeout.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> diff --git a/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_restore.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_restore.S index 991248f5..5cd7a9df 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_restore ARMv8-A-SMP */ -/* 6.1.11 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -277,6 +279,7 @@ __tx_thread_dont_save_ts: /* Set bit indicating this thread is ready for execution. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x2, #1 // Build ready flag STR w2, [x0, #260] // Set thread's ready flag DMB ISH // Ensure that accesses to shared resource have completed diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_save.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_save.S index f43809f5..76641067 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_context_save.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_save ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_control.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_control.S index d4235180..21ec2dd1 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_control.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_control.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_disable.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_disable.S index 08f0e7e1..af2ef874 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_disable.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_disable.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_disable ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_restore.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_restore.S index d0191c32..3e0780d0 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_restore.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_interrupt_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_interrupt_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* _tx_thread_interrupt_restore ARMv8-A */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_schedule.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_schedule.S index 782491cc..de6b70dd 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_schedule.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_schedule ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -156,7 +158,7 @@ _tx_thread_ready_for_execution: LDR x2, =_tx_thread_current_ptr // Pickup address of current thread STR x0, [x2, x20, LSL #3] // Setup current thread pointer - + DMB ISH LDR x1, [x1, x20, LSL #3] // Reload the execute pointer CMP w0, w1 // Did it change? BEQ _execute_pointer_did_not_change // If not, skip handling diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_get.S index 4ffb8cc6..ea14c901 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_preempt.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_preempt.S index 8dc6933c..1d28907f 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_preempt.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_core_preempt.S @@ -19,6 +19,11 @@ /** */ /**************************************************************************/ /**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 .text @@ -27,8 +32,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_preempt Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_preempt ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_state_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_state_get.S index edae94d5..707b41d2 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_state_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_state_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_state_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_state_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_thread_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_thread_get.S index dd740e05..6c4bc9af 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_thread_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_current_thread_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_thread_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_thread_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_initialize_wait.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_initialize_wait.S index 985136b5..defd791c 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_initialize_wait.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_initialize_wait.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_initialize_wait Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_initialize_wait ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_low_level_initialize.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_low_level_initialize.S index 64b854d0..99b20d24 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_low_level_initialize.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_low_level_initialize.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_low_level_initialize Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_low_level_initialize ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_protect.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_protect.S index 4a48c56c..1155a3fa 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_protect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif /* Include macros for modifying the wait list. */ #include "tx_thread_smp_protection_wait_list_macros.h" @@ -31,8 +33,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */ -/* 6.1.11 */ +/* _tx_thread_smp_protect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S index f3045738..4bb9f1cb 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -19,7 +20,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +30,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_time_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_time_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -58,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_unprotect.S index 4b5bd9a2..680e8bc8 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_unprotect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */ -/* 6.1.11 */ +/* _tx_thread_smp_unprotect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_stack_build.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_stack_build.S index fa11a65c..581e259e 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_stack_build.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_stack_build.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_stack_build ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_system_return.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_system_return.S index 4eebb9aa..23c75241 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_system_return.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_system_return ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -159,6 +161,7 @@ __tx_thread_dont_save_ts: /* Set ready bit in thread control block. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x3, #1 // Build ready value STR w3, [x6, #260] // Make the thread ready DMB ISH // diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_timer_interrupt.S b/ports_smp/cortex_a34_smp/ac6/src/tx_timer_interrupt.S index 6f90e5d1..5c6a6bc2 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_timer_interrupt.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_timer_interrupt.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_timer_interrupt ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/readme.md b/ports_smp/cortex_a34_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch index d583631e..385b43c3 100644 --- a/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A34x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> - <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A35x4"/> + <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A34x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a34x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> - <listEntry value=""FVP_Base_Cortex-A35x4""/> + <listEntry value=""FVP_Base_Cortex-A34x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/tx/.cproject b/ports_smp/cortex_a34_smp/gnu/example_build/tx/.cproject index 11d7c2fe..e3f31405 100644 --- a/ports_smp/cortex_a34_smp/gnu/example_build/tx/.cproject +++ b/ports_smp/cortex_a34_smp/gnu/example_build/tx/.cproject @@ -129,9 +129,15 @@ </folderInfo> + <fileInfo id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.config.exe.debug.var.gcc-8.3.0-aarch64-elf.794347674.1482422597" name="tx_misra.c" rcbsApplicability="disable" resourcePath="src_generic/tx_misra.c" toolsToInvoke="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701.1451532610"> + + <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701.1451532610" name="GCC C Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701"/> + + </fileInfo> + <sourceEntries> - <entry excluding="src_generic/tx_misra.c|src_generic/tx_thread_timeout.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> diff --git a/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_initialize_low_level.S b/ports_smp/cortex_a34_smp/gnu/src/tx_initialize_low_level.S index 43d87225..efb08b80 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_initialize_low_level.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_initialize_low_level.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_initialize_low_level ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_restore.S index 991248f5..5cd7a9df 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_restore ARMv8-A-SMP */ -/* 6.1.11 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -277,6 +279,7 @@ __tx_thread_dont_save_ts: /* Set bit indicating this thread is ready for execution. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x2, #1 // Build ready flag STR w2, [x0, #260] // Set thread's ready flag DMB ISH // Ensure that accesses to shared resource have completed diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_save.S index f43809f5..76641067 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_context_save.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_save ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_control.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_control.S index d4235180..21ec2dd1 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_control.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_control.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_disable.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_disable.S index 08f0e7e1..af2ef874 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_disable.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_disable.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_disable ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_restore.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_restore.S index d0191c32..3e0780d0 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_restore.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_interrupt_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_interrupt_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* _tx_thread_interrupt_restore ARMv8-A */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_schedule.S index 782491cc..de6b70dd 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_schedule.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_schedule ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -156,7 +158,7 @@ _tx_thread_ready_for_execution: LDR x2, =_tx_thread_current_ptr // Pickup address of current thread STR x0, [x2, x20, LSL #3] // Setup current thread pointer - + DMB ISH LDR x1, [x1, x20, LSL #3] // Reload the execute pointer CMP w0, w1 // Did it change? BEQ _execute_pointer_did_not_change // If not, skip handling diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_get.S index 4ffb8cc6..ea14c901 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_preempt.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_preempt.S index 8dc6933c..1d28907f 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_preempt.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_core_preempt.S @@ -19,6 +19,11 @@ /** */ /**************************************************************************/ /**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 .text @@ -27,8 +32,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_preempt Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_preempt ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_state_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_state_get.S index edae94d5..707b41d2 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_state_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_state_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_state_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_state_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_thread_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_thread_get.S index dd740e05..6c4bc9af 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_thread_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_current_thread_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_thread_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_thread_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_initialize_wait.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_initialize_wait.S index 985136b5..defd791c 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_initialize_wait.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_initialize_wait.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_initialize_wait Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_initialize_wait ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_low_level_initialize.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_low_level_initialize.S index 64b854d0..99b20d24 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_low_level_initialize.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_low_level_initialize.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_low_level_initialize Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_low_level_initialize ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_protect.S index 4a48c56c..1155a3fa 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_protect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif /* Include macros for modifying the wait list. */ #include "tx_thread_smp_protection_wait_list_macros.h" @@ -31,8 +33,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */ -/* 6.1.11 */ +/* _tx_thread_smp_protect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S index f3045738..4bb9f1cb 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -19,7 +20,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +30,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_time_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_time_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -58,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_unprotect.S index 4b5bd9a2..680e8bc8 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_unprotect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */ -/* 6.1.11 */ +/* _tx_thread_smp_unprotect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_stack_build.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_stack_build.S index fa11a65c..581e259e 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_stack_build.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_stack_build.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_stack_build ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_system_return.S index 4eebb9aa..23c75241 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_system_return.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_system_return ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -159,6 +161,7 @@ __tx_thread_dont_save_ts: /* Set ready bit in thread control block. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x3, #1 // Build ready value STR w3, [x6, #260] // Make the thread ready DMB ISH // diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_timer_interrupt.S b/ports_smp/cortex_a34_smp/gnu/src/tx_timer_interrupt.S index 6f90e5d1..5c6a6bc2 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_timer_interrupt.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_timer_interrupt.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_timer_interrupt ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 5a0bdcf4..639e2f4e 100644 --- a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A35x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/readme.md b/ports_smp/cortex_a35_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch index d583631e..d06144eb 100644 --- a/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A35x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 27743868..dc48da27 100644 --- a/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A53x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A53x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a53x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A53x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/readme.md b/ports_smp/cortex_a53_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch index d0fd074c..34ec164b 100644 --- a/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A53x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A53x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a53x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A53x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch index f642a3e4..4b336147 100644 --- a/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A55x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A55x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a55x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A55x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/readme.md b/ports_smp/cortex_a55_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 2f22ba75..2ad35b44 100644 --- a/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A55x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A55x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a55x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A55x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 674e9663..fb3877c6 100644 --- a/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A57x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A57x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a57x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A57x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/readme.md b/ports_smp/cortex_a57_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 17c737ee..40fa00b6 100644 --- a/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A57x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A57x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a57x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A57x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h index 0db5a292..30e2719a 100644 --- a/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h @@ -388,7 +388,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s index 21d63d05..a3ca9ad7 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore ; { ; __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; - MOV r0, r10 ; Move the core ID to r0 for the macro -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s index 33047893..1217a5e5 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s index e4c232aa..b24e941e 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -164,6 +167,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s index a7419c10..ca3eb3ea 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -31,17 +33,9 @@ ; ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -80,12 +74,12 @@ ;/**************************************************************************/ EXPORT _tx_thread_smp_protect _tx_thread_smp_protect - - PUSH {r4-r6} ; Save registers we'll be using +;VOID _tx_thread_smp_protect(VOID) +;{ ; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -93,266 +87,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -360,4 +181,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index fec51581..00000000 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,314 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r0 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register - AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r0, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r0, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s index a378060e..f6e7f066 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -69,7 +71,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + LDR r0, [r0, #0x200] ; Read global timer count low register IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +80,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s index 61645b3e..5dad99a8 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s index da21d7c1..a2880c1d 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s index 69a22693..7e152dfe 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..28c41af5 --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX port sources for cortex_a5_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..88c68def --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A5 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..7ed4946e --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,56 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A5 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" + # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a5 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_SCU.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_PrivateTimer.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a5 -nostartfiles \ + -T sample_threadx.ld \ + ${ENTRY_FLAG} \ + ${SYSCALL_LIB} \ + -o sample_threadx.out \ + MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S new file mode 100644 index 00000000..abc817d5 --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.s b/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.S index 56066e5d..56066e5d 100644 --- a/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.s +++ b/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.S diff --git a/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h index deb71768..b60e132f 100644 --- a/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h @@ -391,7 +391,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S index 53ca2cc2..e320303b 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -29,8 +31,6 @@ @#include "tx_thread.h" @#include "tx_timer.h" @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" #ifdef TX_ENABLE_FIQ_SUPPORT DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore: @ { @ __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - MOV r0, r10 @ Move the core ID to r0 for the macro - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S index 3148c0f5..299d5a0d 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -147,11 +149,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S index 00f254dd..5ef6af30 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -166,6 +169,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S index db0a2525..560fa8df 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -31,17 +33,9 @@ @ @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -82,12 +76,12 @@ .global _tx_thread_smp_protect .type _tx_thread_smp_protect,function _tx_thread_smp_protect: - - PUSH {r4-r6} @ Save registers we'll be using +@VOID _tx_thread_smp_protect(VOID) +@{ @ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -95,270 +89,96 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2, #0] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: -@ -@ /* Restore interrupts. */ +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ +_got_protection: @ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f1ad80e8..00000000 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,309 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r0 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - MRC p15, 0, r0, c0, c0, 5 @ Read CPU ID register - AND r0, r0, #0x03 @ Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r0, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r0, LSL #2] @ Store new waiting value - .endm - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S index 7e399690..f9ecf1b5 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -71,7 +73,7 @@ _tx_thread_smp_time_get: MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + LDR r0, [r0, #0x200] @ Read global timer count low register #ifdef __THUMB_INTERWORK BX lr @ Return to caller @@ -79,4 +81,3 @@ _tx_thread_smp_time_get: MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S index 4cccae92..e00f53ec 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S index f49d8324..4451fdd5 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S index aed336ad..67711a9c 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 1bb76fab..1324b9bd 100644 --- a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -210,13 +210,6 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -387,17 +380,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A53x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch index fc1a8ba9..e64d68f8 100644 --- a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch +++ b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch @@ -207,17 +207,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> -<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> -<listEntry value="NODE CACHE VERSION 1"/> -<listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> -<listEntry value="1"/> -<listEntry value="formatter"/> -<listEntry value="Hexadecimal"/> -</listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> -<stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints> 	<breakpoint location_expression="EL1N:l64_fiq" ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="EXPRESSION"> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000400"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x0000000080000400" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/vectors.S" line="79"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x0000000080000200" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/vectors.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\vectors.S" line="61"/> 		<location index="0" enabled="true" version="2" address="EL3:0x0000000080000200" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/vectors.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\vectors.S" line="61"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x00000000800009F8"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x00000000800009F8" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/entry.S" line="274"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000CCC"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x0000000080000CCC" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_context_save.S" line="253"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000FA0"/> 		<location index="0" enabled="false" version="2" address="EL1N:0x0000000080000FA0" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_schedule.S" line="244"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x000000008000628C"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x000000008000628C" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_shell_entry.c" line="254"/> 	</breakpoint> 	<breakpoint location_expression="EL2N:0x800009f8" ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="EXPRESSION"> 		<master_location index="0" enabled="true" version="2" address="EL2N:0x00000000800009F8"/> 		<location index="0" enabled="false" version="2" address="EL2N:0x00000000800009F8"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x000000008000BF88"/> 		<location index="0" enabled="false" version="2" address="EL1N:0x000000008000BF88" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/sample_threadx.c" line="239"/> 	</breakpoint> 	<breakpoint location_expression="EL1N:0x0000000080000D84" ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="EXPRESSION"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000D84"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x0000000080000D84" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_timer_interrupt.S" line="128"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="false" version="2" address="EL1N:0x0000000080000F40"/> 		<location index="0" enabled="false" version="2" address="EL1N:0x0000000080000F40" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_schedule.S" line="164"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x000000008000BFC8"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x000000008000BFC8" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/sample_threadx.c" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\sample_threadx.c" line="251"/> 	</breakpoint> 	<breakpoint location_expression="EL1N:0x80000200" ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="EXPRESSION"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000200"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x0000000080000200" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/vectors.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\vectors.S" line="61"/> 	</breakpoint> 	<breakpoint location_expression="EL3:0x0000000080000D84" ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="EXPRESSION"> 		<master_location index="0" enabled="false" version="2" address="EL3:0x0000000080000D84" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_timer_interrupt.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\tx\tx_timer_interrupt.S" line="128"/> 		<location index="0" enabled="true" version="2" address="EL3:0x0000000080000D84" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_timer_interrupt.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\tx\tx_timer_interrupt.S" line="128"/> 	</breakpoint> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="RAW_EXEC_ADDRESS"> 		<master_location index="0" enabled="true" version="2" address="EL1N:0x0000000080000000"/> 		<location index="0" enabled="true" version="2" address="EL1N:0x0000000080000000" debugFile="B:/support/broadcom/tx58cortexa53arm/release/threadx/sample_threadx/vectors.S" hostFile="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\vectors.S" line="38"/> 	</breakpoint> </breakpoints> "/> +<stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value="$pc"/> <listEntry value=""/> @@ -388,14 +381,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> -<mapAttribute key="scripts_view_script_links"> -<mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> -</mapAttribute> <listAttribute key="setup"> <listEntry value="DS5://sw/debugger/configdb/Scripts/rtsm_launcher.py"/> <listEntry value="DS5://bin/FVP_Base_AEMv8A"/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> -<stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h index 2000b6f5..14b1f783 100644 --- a/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h @@ -412,7 +412,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "Copyright (c) 1996-2019 Express Logic Inc. * ThreadX Cortex-A5x-SMP/AC6 Version 6.5.1.202602a *"; + "Copyright (c) 1996-2019 Express Logic Inc. * ThreadX Cortex-A5x-SMP/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S index efa6d62c..7a20db32 100644 --- a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..08db4117 --- /dev/null +++ b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX port sources for cortex_a5x_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 2718a398..d5d36204 100644 --- a/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -233,13 +233,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -414,21 +407,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a5x_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A53x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h index 90e2da85..25494438 100644 --- a/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h @@ -412,7 +412,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S index 4a98140a..4b3ee1d4 100644 --- a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/green/inc/tx_port.h b/ports_smp/cortex_a5x_smp/green/inc/tx_port.h index 50476b1c..bae66fef 100644 --- a/ports_smp/cortex_a5x_smp/green/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/green/inc/tx_port.h @@ -432,7 +432,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GHS Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GHS Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 index 45d286b0..37514c26 100644 --- a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 +++ b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -76,7 +78,7 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // Add time source - application specific + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h b/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h index 0bd49528..29003aee 100644 --- a/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h @@ -441,7 +441,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S index 43834196..16cdf26d 100644 --- a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -70,7 +71,7 @@ /**************************************************************************/ PUBLIC _tx_thread_smp_time_get _tx_thread_smp_time_get: - MOV x0, #0 // Add logic to get timer value here for diagnostics + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET END diff --git a/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 35b90705..40148e64 100644 --- a/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A65x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A65x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a65x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A65x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/readme.md b/ports_smp/cortex_a65_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch index bc7dcad0..936fbc87 100644 --- a/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A65x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A65x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a65x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A65x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 09d5f09b..7075858b 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A65AEx4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A65AEx4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a65aex4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A65AEx4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/readme.md b/ports_smp/cortex_a65ae_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 0ffed216..6fbaed29 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A65AEx4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A65AEx4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a65aex4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A65AEx4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 354f9ea7..6e400036 100644 --- a/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A72x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A72x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a72x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A72x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/readme.md b/ports_smp/cortex_a72_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 6a746fbc..0e0032ae 100644 --- a/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A72x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A72x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a72x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A72x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch index d9e3d93f..01e2095c 100644 --- a/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A73x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A73x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a73x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A73x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/readme.md b/ports_smp/cortex_a73_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 1cc749ae..dbd26b95 100644 --- a/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A73x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A73x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a73x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A73x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 28c5aab8..48c03e62 100644 --- a/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A75x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A75x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a75x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A75x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/readme.md b/ports_smp/cortex_a75_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 76a6ad45..f2e1d3a7 100644 --- a/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A75x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A75x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a75x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A75x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h index 31eb4f24..38c86cb2 100644 --- a/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h @@ -187,7 +187,7 @@ typedef unsigned long long ALIGN_TYPE; /* Define various constants for the ThreadX ARM port. */ #define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */ -#define TX_INT_ENABLE 0x00 /* Enable IRQ & FIQ interrupts */ +#define TX_INT_ENABLE 0x00 /* Enable IRQ & FIQ interrupts */ /* Define the clock source for trace event entry time stamp. The following two item are port specific. @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch index a665e8c3..557f8e3e 100644 --- a/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A76x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A76x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a76x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A76x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/readme.md b/ports_smp/cortex_a76_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 58967dca..ef5c7bf7 100644 --- a/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A76x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A76x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a76x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A76x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch index f261e124..b140704f 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A76AEx4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A76AEx4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a76aex4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A76AEx4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/readme.md b/ports_smp/cortex_a76ae_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 8108d076..44fc82c0 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A76AEx4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A76AEx4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a76aex4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A76AEx4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 8d2fe10c..956df926 100644 --- a/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> - <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/> + <stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> </breakpoints> "/> <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses"> <listEntry value=""/> <listEntry value="<Next Instruction>"/> @@ -316,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A77x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A77x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a77x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -395,19 +388,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A77x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/readme.md b/ports_smp/cortex_a77_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch index a7f12edc..e33dfa12 100644 --- a/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A77x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A77x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a77x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> <listEntry value=""FVP_Base_Cortex-A77x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S index 335824fb..4bb9f1cb 100644 --- a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/.cproject b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/.cproject index 67ef2a0c..4e305710 100644 --- a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/.cproject +++ b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/.cproject @@ -29,7 +29,7 @@ <toolChain id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.base.var.arm_compiler_6-6"> - <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1337922098" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="cortex-a78.AArch64.ARMv8.Neon.Crypto" valueType="string"/> + <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1337922098" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A78.AArch64.ARMv8.Neon.Crypto" valueType="string"/> <targetPlatform id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597.2060144338" name=""/> diff --git a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 9aefbdcd..aac92dec 100644 --- a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -6,17 +6,17 @@ <stringAttribute key="ANDROID_PROCESS_NAME" value=""/> <mapAttribute key="AverageDurationTracker"> <mapEntry key="*Fetching Data" value="34126331"/> - <mapEntry key="*Fetching Data Model" value="1439173"/> + <mapEntry key="*Fetching Data Model" value="1887986"/> <mapEntry key="*FunctionLoader" value="137168653"/> - <mapEntry key="*list global low level symbols" value="2707112"/> + <mapEntry key="*list global low level symbols" value="3163826"/> <mapEntry key="*loading memory from target" value="2367919"/> - <mapEntry key="*loading values from target" value="8477514"/> + <mapEntry key="*loading values from target" value="8665557"/> <mapEntry key="*trace" value="1527238"/> - <mapEntry key="*updating expressions" value="101886453"/> + <mapEntry key="*updating expressions" value="25251903"/> <mapEntry key="*updating local_variables" value="836905"/> <mapEntry key="*updating registers" value="97090462"/> <mapEntry key="*updating variables" value="877039"/> - <mapEntry key="AddEventObserver" value="6587743"/> + <mapEntry key="AddEventObserver" value="5292071"/> <mapEntry key="Evaluate" value="1689813"/> <mapEntry key="ResumeToHere" value="20159012"/> <mapEntry key="Retrieving globals list" value="21298708"/> @@ -24,11 +24,11 @@ <mapEntry key="backtrace" value="21505977"/> <mapEntry key="break" value="9764564"/> <mapEntry key="checking tracepoints" value="372731"/> - <mapEntry key="compute execution mode" value="557345"/> + <mapEntry key="compute execution mode" value="835755"/> <mapEntry key="console" value="11946310"/> - <mapEntry key="continue" value="12697403"/> + <mapEntry key="continue" value="21247618"/> <mapEntry key="core" value="5451456"/> - <mapEntry key="directory" value="4737162"/> + <mapEntry key="directory" value="4479981"/> <mapEntry key="disable" value="2444670"/> <mapEntry key="disassemble" value="64135505"/> <mapEntry key="enable" value="5445745"/> @@ -36,40 +36,41 @@ <mapEntry key="evaluate address" value="1056014"/> <mapEntry key="finish" value="20115248"/> <mapEntry key="get byte order" value="633302"/> - <mapEntry key="get capabilities" value="548556"/> - <mapEntry key="get execution addresss" value="438164"/> - <mapEntry key="get source lines" value="3151194"/> - <mapEntry key="get substitute paths" value="293110"/> + <mapEntry key="get capabilities" value="382078"/> + <mapEntry key="get execution addresss" value="403253"/> + <mapEntry key="get source lines" value="951928"/> + <mapEntry key="get substitute paths" value="523052"/> <mapEntry key="getValidEncodings" value="1202320"/> - <mapEntry key="initialize command help" value="68196070"/> + <mapEntry key="initialize command help" value="63855085"/> <mapEntry key="interrupt" value="11210435"/> - <mapEntry key="list breakpoint options" value="1264804"/> - <mapEntry key="list breakpoints" value="1473749"/> - <mapEntry key="list instruction sets" value="1512051"/> - <mapEntry key="list signals" value="1314040"/> + <mapEntry key="list breakpoint options" value="2030851"/> + <mapEntry key="list breakpoints" value="1627224"/> + <mapEntry key="list instruction sets" value="1847125"/> + <mapEntry key="list signals" value="1953020"/> <mapEntry key="list source files" value="573423"/> - <mapEntry key="list watchpoint options" value="4130737"/> - <mapEntry key="list watchpoints" value="739118"/> - <mapEntry key="loadfile" value="308178719"/> + <mapEntry key="list watchpoint options" value="6057468"/> + <mapEntry key="list watchpoints" value="970059"/> + <mapEntry key="loadfile" value="386648009"/> <mapEntry key="next" value="24266800"/> <mapEntry key="query supports threads" value="215433"/> - <mapEntry key="remove" value="3597385"/> - <mapEntry key="run script" value="37326822"/> - <mapEntry key="set CWD" value="4366642"/> + <mapEntry key="remove" value="7663692"/> + <mapEntry key="run script" value="44460661"/> + <mapEntry key="set CWD" value="5180571"/> <mapEntry key="set breakpoint properties" value="10666013"/> - <mapEntry key="set debug-from" value="1215725"/> - <mapEntry key="set substitute-path" value="23083827"/> - <mapEntry key="source use_model_semihosting.ds" value="7540462"/> - <mapEntry key="start" value="36728254"/> + <mapEntry key="set debug-from" value="1157012"/> + <mapEntry key="set substitute-path" value="27245163"/> + <mapEntry key="source use_model_semihosting.ds" value="8849881"/> + <mapEntry key="start" value="50528177"/> <mapEntry key="step" value="26461127"/> <mapEntry key="stepi" value="29574773"/> <mapEntry key="synchronizing trace ranges" value="21582"/> <mapEntry key="target reset" value="32992642"/> - <mapEntry key="toggleBreakpoint" value="7875634"/> + <mapEntry key="toggleBreakpoint" value="19462208"/> <mapEntry key="updateBreakpointLocation" value="1868000"/> - <mapEntry key="waitForTargetToStop" value="47515299"/> + <mapEntry key="waitForTargetToStop" value="52570549"/> <mapEntry key="write expression" value="21220700"/> </mapAttribute> + <stringAttribute key="CLOCK_SPEED" value="Auto"/> <listAttribute key="DEBUG_TAB."/> <stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/> <stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx}"/> @@ -89,15 +90,15 @@ <stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.VALUE" value=""/> <intAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.COUNT" value="1"/> <listAttribute key="FILES.DEBUG_RESIDENT_APP"/> - <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="APPLICATION_ON_TARGET"/> <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.VALUE" value=""/> - <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="APPLICATION_ON_TARGET"/> + <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.VALUE" value=""/> <intAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.COUNT" value="2"/> <listAttribute key="FILES.DOWNLOAD_AND_DEBUG"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/> @@ -105,13 +106,13 @@ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.VALUE" value=""/> <intAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.COUNT" value="3"/> <listAttribute key="FILES.DOWNLOAD_DEBUG"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/> @@ -119,7 +120,7 @@ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/> - <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/> + <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/> <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.VALUE" value=""/> <intAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.COUNT" value="3"/> <intAttribute key="FILES.DOWNLOAD_DEBUG_ANDROID.RESOURCES.COUNT" value="0"/> @@ -162,6 +163,8 @@ <intAttribute key="POST_TRIGGER_CAPTURE_SIZE" value="50"/> <booleanAttribute key="RSE_USE_HOSTNAME" value="true"/> <booleanAttribute key="STOP_ON_TRIGGER" value="false"/> + <booleanAttribute key="SWD" value="false"/> + <booleanAttribute key="SWJ" value="true"/> <stringAttribute key="TCP_DISABLE_EXTENDED_MODE" value="true"/> <booleanAttribute key="TCP_KILL_ON_EXIT" value="false"/> <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.ExpressionsView"> @@ -211,13 +214,6 @@ <listEntry value="element formatter"/> <listEntry value="Hexadecimal"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -313,13 +309,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A78x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> - <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A35x4"/> + <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A78x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a78x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -363,7 +359,7 @@ <mapEntry key="6" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/> <mapEntry key="7" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/> </mapAttribute> - <stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	187	-1	true	1	false	true	90	-1	true	2	true	true	108	-1	true	3	true	true	57	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	148	-1	true	7	true	true	53	-1	true"/> + <stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	255	-1	true	1	false	true	127	-1	true	2	true	true	159	-1	true	3	true	true	75	-1	true	4	true	true	65	-1	true	5	true	true	48	-1	true	6	true	true	241	-1	true	7	true	true	69	-1	true"/> <stringAttribute key="debugger.view.MemoryView" value="<?xml version="1.0" encoding="UTF-8"?> <page> 	<memoryView/> </page> "/> <listAttribute key="debugger.view.MemoryView:current"> <listEntry value=""/> @@ -386,24 +382,16 @@ <stringAttribute key="dtsl_options_file" value="default"/> <stringAttribute key="dtsl_tracecapture_option" value="options.trace.traceCapture"/> <booleanAttribute key="linuxOS" value="false"/> - <stringAttribute key="model_connection_address" value=""/> + <stringAttribute key="model_connection_address" value="127.0.0.1:7100"/> <stringAttribute key="model_iris" value="1"/> <stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/> <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> - <listEntry value=""FVP_Base_Cortex-A35x4""/> + <listEntry value=""FVP_Base_Cortex-A78x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a78_smp/ac6/example_build/tx/.cproject b/ports_smp/cortex_a78_smp/ac6/example_build/tx/.cproject index 5896ab3a..c049b3a6 100644 --- a/ports_smp/cortex_a78_smp/ac6/example_build/tx/.cproject +++ b/ports_smp/cortex_a78_smp/ac6/example_build/tx/.cproject @@ -7,7 +7,19 @@ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944" moduleId="org.eclipse.cdt.core.settings" name="Debug"> - <externalSettings/> + <externalSettings> + + <externalSetting> + + <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/tx"/> + + <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/tx/Debug"/> + + <entry flags="RESOLVED" kind="libraryFile" name="tx" srcPrefixMapping="" srcRootPath=""/> + + </externalSetting> + + </externalSettings> <extensions> @@ -29,7 +41,7 @@ <toolChain id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1684503312" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6"> - <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.982423385" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="cortex-a78.AArch64.ARMv8.Neon.Crypto" valueType="string"/> + <option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.982423385" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A78.AArch64.ARMv8.Neon.Crypto" valueType="string"/> <targetPlatform id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.1684503312.2127819066" name=""/> @@ -105,9 +117,25 @@ </folderInfo> + <fileInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944.214318543" name="tx_thread_timeout.c" rcbsApplicability="disable" resourcePath="src_generic/tx_thread_timeout.c" toolsToInvoke="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1899536638"> + + <tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1899536638" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428"> + + <inputType id="com.arm.tool.c.compiler.v6.base.input.1006773355" superClass="com.arm.tool.c.compiler.v6.base.input"/> + + </tool> + + </fileInfo> + + <fileInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1470528944.1145515026" name="tx_misra.c" rcbsApplicability="disable" resourcePath="src_generic/tx_misra.c" toolsToInvoke="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1242981128"> + + <tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428.1242981128" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.2072709428"/> + + </fileInfo> + <sourceEntries> - <entry excluding="src_generic/tx_misra.c|src_generic/tx_thread_timeout.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> diff --git a/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_restore.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_restore.S index e2c48868..5cd7a9df 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_restore.S @@ -19,10 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - - -/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -207,74 +206,6 @@ __tx_thread_no_preempt_restore: // { __tx_thread_preempt_restore: - /* Was the thread being preempted waiting for the lock? */ - // if (_tx_thread_smp_protect_wait_counts[this_core] != 0) - // { - - LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list - LDR w3, [x2, x8, LSL #2] // Load waiting value for this core - CMP w3, #0 - BEQ _nobody_waiting_for_lock // Is the core waiting for the lock? - - /* Do we not have the lock? This means the ISR never got the inter-core lock. */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) - // { - - LDR x2, =_tx_thread_smp_protection // Load address of protection structure - LDR w3, [x2, #4] // Pickup the owning core - CMP w8, w3 // Compare our core to the owning core - BEQ _this_core_has_lock // Do we have the lock? - - /* We don't have the lock. This core should be in the list. Remove it. */ - // _tx_thread_smp_protect_wait_list_remove(this_core); - - _tx_thread_smp_protect_wait_list_remove // Call macro to remove core from the list - B _nobody_waiting_for_lock // Leave - - // } - // else - // { - /* We have the lock. This means the ISR got the inter-core lock, but - never released it because it saw that there was someone waiting. - Note this core is not in the list. */ - -_this_core_has_lock: - - /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ - // _tx_thread_smp_protect_wait_counts[core]--; - - LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list - LDR w3, [x2, x8, LSL #2] // Load waiting value for this core - SUB w3, w3, #1 // Decrement waiting value. Should be zero now - STR w3, [x2, x8, LSL #2] // Store new waiting value - - /* Now release the inter-core lock. */ - - /* Set protected core as invalid. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; - - LDR x2, =_tx_thread_smp_protection // Load address of protection structure - MOV w3, #0xFFFFFFFF // Build invalid value - STR w3, [x2, #4] // Mark the protected core as invalid - DMB ISH // Ensure that accesses to shared resource have completed - - /* Release protection. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; - - MOV w3, #0 // Build release protection value - STR w3, [x2, #0] // Release the protection - DSB ISH // To ensure update of the protection occurs before other CPUs awake - - /* Wake up waiting processors. Note interrupts are already enabled. */ - -#ifdef TX_ENABLE_WFE - SEV // Send event to other CPUs -#endif - - // } - // } - -_nobody_waiting_for_lock: LDR x4, [x0, #8] // Switch to thread stack pointer MOV sp, x4 // @@ -348,6 +279,7 @@ __tx_thread_dont_save_ts: /* Set bit indicating this thread is ready for execution. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x2, #1 // Build ready flag STR w2, [x0, #260] // Set thread's ready flag DMB ISH // Ensure that accesses to shared resource have completed diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_save.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_save.S index f43809f5..76641067 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_context_save.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_save ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_control.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_control.S index d4235180..21ec2dd1 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_control.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_control.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_disable.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_disable.S index 08f0e7e1..af2ef874 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_disable.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_disable.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_disable ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_restore.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_restore.S index d0191c32..3e0780d0 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_restore.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_interrupt_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_interrupt_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* _tx_thread_interrupt_restore ARMv8-A */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_schedule.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_schedule.S index 782491cc..de6b70dd 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_schedule.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_schedule ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -156,7 +158,7 @@ _tx_thread_ready_for_execution: LDR x2, =_tx_thread_current_ptr // Pickup address of current thread STR x0, [x2, x20, LSL #3] // Setup current thread pointer - + DMB ISH LDR x1, [x1, x20, LSL #3] // Reload the execute pointer CMP w0, w1 // Did it change? BEQ _execute_pointer_did_not_change // If not, skip handling diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_get.S index 4ffb8cc6..ea14c901 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_preempt.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_preempt.S index 8dc6933c..1d28907f 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_preempt.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_core_preempt.S @@ -19,6 +19,11 @@ /** */ /**************************************************************************/ /**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 .text @@ -27,8 +32,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_preempt Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_preempt ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_state_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_state_get.S index edae94d5..707b41d2 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_state_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_state_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_state_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_state_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_thread_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_thread_get.S index dd740e05..6c4bc9af 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_thread_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_current_thread_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_thread_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_thread_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_initialize_wait.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_initialize_wait.S index 985136b5..defd791c 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_initialize_wait.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_initialize_wait.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_initialize_wait Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_initialize_wait ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_low_level_initialize.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_low_level_initialize.S index 64b854d0..99b20d24 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_low_level_initialize.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_low_level_initialize.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_low_level_initialize Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_low_level_initialize ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_protect.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_protect.S index 30a43701..1155a3fa 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_protect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif /* Include macros for modifying the wait list. */ #include "tx_thread_smp_protection_wait_list_macros.h" @@ -31,8 +33,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_protect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -71,293 +73,49 @@ _tx_thread_smp_protect: /* Pickup the CPU ID. */ - MRS x1, MPIDR_EL1 // Pickup the core ID + MRS x2, MPIDR_EL1 // Pickup the core ID #ifdef TX_ARMV8_2 #if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #16, #8 // Isolate cluster ID + UBFX x7, x2, #16, #8 // Isolate cluster ID #endif - UBFX x1, x1, #8, #8 // Isolate core ID + UBFX x2, x2, #8, #8 // Isolate core ID #else #if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #8, #8 // Isolate cluster ID + UBFX x7, x2, #8, #8 // Isolate cluster ID #endif - UBFX x1, x1, #0, #8 // Isolate core ID + UBFX x2, x2, #0, #8 // Isolate core ID #endif #if TX_THREAD_SMP_CLUSTERS > 1 - ADDS x1, x1, x7, LSL #2 // Calculate CPU ID + ADDS x2, x2, x7, LSL #2 // Calculate CPU ID #endif - /* Do we already have protection? */ - // if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) - // { - - LDR x2, =_tx_thread_smp_protection // Build address to protection structure - LDR w3, [x2, #4] // Pickup the owning core - CMP w1, w3 // Is it not this core? - BNE _protection_not_owned // No, the protection is not already owned - - /* We already have protection. */ - - /* Increment the protection count. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_count++; - - LDR w3, [x2, #8] // Pickup ownership count - ADD w3, w3, #1 // Increment ownership count - STR w3, [x2, #8] // Store ownership count - DMB ISH - - B _return - -_protection_not_owned: - - /* Is the lock available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _start_waiting // No, protection not available - - /* Is the list empty? */ - // if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head - LDR w3, [x3] - LDR x4, =_tx_thread_smp_protect_wait_list_tail - LDR w4, [x4] - CMP w3, w4 - BNE _list_not_empty - - /* Try to get the lock. */ - // if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) - // { - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _start_waiting // Did it fail? - - /* We got the lock! */ - // _tx_thread_smp_protect_lock_got(); - - DMB ISH // Ensure write to protection finishes - _tx_thread_smp_protect_lock_got // Call the lock got function - - B _return - -_list_not_empty: - - /* Are we at the front of the list? */ - // if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head - LDR w3, [x3] // Get the value of the head - LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list - LDR w4, [x4, x3, LSL #2] // Get the value at the head index - - CMP w1, w4 - BNE _start_waiting - - /* Is the lock still available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _start_waiting // No, protection not available - - /* Get the lock. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _start_waiting // Did it fail? - DMB ISH // - - /* Got the lock. */ - // _tx_thread_smp_protect_lock_got(); - - _tx_thread_smp_protect_lock_got - - /* Remove this core from the wait list. */ - // _tx_thread_smp_protect_remove_from_front_of_list(); - - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: - - /* For one reason or another, we didn't get the lock. */ - - /* Increment wait count. */ - // _tx_thread_smp_protect_wait_counts[this_core]++; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - ADD w4, w4, #1 // Increment wait value - STR w4, [x3, x1, LSL #2] // Store new wait value - - /* Have we not added ourselves to the list yet? */ - // if (_tx_thread_smp_protect_wait_counts[this_core] == 1) - // { - - CMP w4, #1 - BNE _already_in_list0 // Is this core already waiting? - - /* Add ourselves to the list. */ - // _tx_thread_smp_protect_wait_list_add(this_core); - - _tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list - - // } - -_already_in_list0: - - /* Restore interrupts. */ + LDR x1, =_tx_thread_smp_protection // Build address to protection structure + LDR w3, [x1, #4] // Pickup the owning core + CMP w3, w2 // Is it this core? + BEQ _owned // Yes, the protection is already owned + LDAXR w4, [x1, #0] // Pickup the protection flag + CBZ w4, _get_protection // Yes, get the protection MSR DAIF, x0 // Restore interrupts ISB // #ifdef TX_ENABLE_WFE WFE // Go into standby #endif + B _tx_thread_smp_protect // On waking, restart the protection attempt - /* We do this until we have the lock. */ - // while (1) - // { - -_try_to_get_lock: - - /* Disable interrupts so we don't get preempted. */ - - MRS x0, DAIF // Pickup current interrupt posture - MSR DAIFSet, 0x3 // Lockout interrupts - - /* Pickup the CPU ID. */ - - MRS x1, MPIDR_EL1 // Pickup the core ID -#ifdef TX_ARMV8_2 -#if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #16, #8 // Isolate cluster ID -#endif - UBFX x1, x1, #8, #8 // Isolate core ID -#else -#if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #8, #8 // Isolate cluster ID -#endif - UBFX x1, x1, #0, #8 // Isolate core ID -#endif -#if TX_THREAD_SMP_CLUSTERS > 1 - ADDS x1, x1, x7, LSL #2 // Calculate CPU ID -#endif - - /* Do we already have protection? */ - // if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) - // { - - LDR w3, [x2, #4] // Pickup the owning core - CMP w3, w1 // Is it this core? - BEQ _got_lock_after_waiting // Yes, the protection is already owned. This means - // an ISR preempted us and got protection - - // } - - /* Are we at the front of the list? */ - // if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head - LDR w3, [x3] // Get the value of the head - LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list - LDR w4, [x4, x3, LSL #2] // Get the value at the head index - - CMP w1, w4 - BNE _did_not_get_lock - - /* Is the lock still available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _did_not_get_lock // No, protection not available - - /* Get the lock. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _did_not_get_lock // Did it fail? - DMB ISH // - - /* Got the lock. */ - // _tx_thread_smp_protect_lock_got(); - - _tx_thread_smp_protect_lock_got - - /* Remove this core from the wait list. */ - // _tx_thread_smp_protect_remove_from_front_of_list(); - - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting - -_did_not_get_lock: - - /* For one reason or another, we didn't get the lock. */ - - /* Were we removed from the list? This can happen if we're a thread - and we got preempted. */ - // if (_tx_thread_smp_protect_wait_counts[this_core] == 0) - // { - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - CMP w4, #0 - BNE _already_in_list1 // Is this core already in the list? - - /* Add ourselves to the list. */ - // _tx_thread_smp_protect_wait_list_add(this_core); - - _tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list - - /* Our waiting count was also reset when we were preempted. Increment it again. */ - // _tx_thread_smp_protect_wait_counts[this_core]++; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - ADD w4, w4, #1 // Increment wait value - STR w4, [x3, x1, LSL #2] // Store new wait value value - - // } - -_already_in_list1: - - /* Restore interrupts and try again. */ - +_get_protection: + MOV x4, #1 // Build lock value + STXR w5, w4, [x1] // Attempt to get the protection + CBZ w5, _got_protection // Did it succeed? w5 = 0 means success! MSR DAIF, x0 // Restore interrupts - ISB // -#ifdef TX_ENABLE_WFE - WFE // Go into standby -#endif - B _try_to_get_lock // On waking, restart the protection attempt - -_got_lock_after_waiting: - - /* We're no longer waiting. */ - // _tx_thread_smp_protect_wait_counts[this_core]--; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load waiting list - LDR w4, [x3, x1, LSL #2] // Load current wait value - SUB w4, w4, #1 // Decrement wait value - STR w4, [x3, x1, LSL #2] // Store new wait value value - - /* Restore registers and return. */ - -_return: + B _tx_thread_smp_protect // Restart the protection attempt +_got_protection: + DMB ISH // + STR w2, [x1, #4] // Save owning core +_owned: + LDR w5, [x1, #8] // Pickup ownership count + ADD w5, w5, #1 // Increment ownership count + STR w5, [x1, #8] // Store ownership count + DMB ISH // RET diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S index f3045738..4bb9f1cb 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -19,7 +20,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +30,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_time_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_time_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -58,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_unprotect.S index 49af176a..680e8bc8 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_unprotect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_unprotect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -96,11 +98,6 @@ _tx_thread_smp_unprotect: CMP w3, #0 // Is the preempt disable flag set? BNE _still_protected // Yes, skip the protection release - LDR x2,=_tx_thread_smp_protect_wait_counts // Build build address of wait counts - LDR w3, [x2, x1, LSL #2] // Pickup wait list value - CMP w3, #0 // Are any entities on this core waiting? - BNE _still_protected // Yes, skip the protection release - LDR x2,=_tx_thread_smp_protection // Build address of protection structure MOV w3, #0xFFFFFFFF // Build invalid value STR w3, [x2, #4] // Mark the protected core as invalid diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_stack_build.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_stack_build.S index fa11a65c..581e259e 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_stack_build.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_stack_build.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_stack_build ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_system_return.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_system_return.S index 4eebb9aa..23c75241 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_system_return.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_system_return ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -159,6 +161,7 @@ __tx_thread_dont_save_ts: /* Set ready bit in thread control block. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x3, #1 // Build ready value STR w3, [x6, #260] // Make the thread ready DMB ISH // diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_timer_interrupt.S b/ports_smp/cortex_a78_smp/ac6/src/tx_timer_interrupt.S index 6f90e5d1..5c6a6bc2 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_timer_interrupt.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_timer_interrupt.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_timer_interrupt ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..36f7492b --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..b3b2cd36 --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the ThreadX library, tx.a, for the AArch64 port this script sits in. +# The AArch64 examples previously had no build driver at all and could only be +# built through Arm Development Studio project files. +# +# ./build_threadx.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +# +# The CPU is derived from the directory this script lives in, so one script +# serves every AArch64 port rather than needing one copy per core. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +# ports/<core>/gnu/example_build -> up two levels is <core> -> the -mcpu name. +# The same example tree is copied into the SMP ports, where the core directory +# carries an _smp suffix and the kernel sources live in common_smp. +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + AR="aarch64-none-elf-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=aarch64-none-elf" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc" + +echo "Building tx.a for ${cpu} with ${TOOLCHAIN}" + +rm -f tx.a ./*.o + +# Port sources. The SMP ports carry C sources here as well as assembly. +for src in ../src/*.S ../src/*.c; do + [ -f "${src}" ] || continue + obj="$(basename "${src}")" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj%.*}.o" +done + +# Common ThreadX sources. tx_misra.c is deliberately excluded: it is only for +# MISRA builds and has an assembly counterpart in the port. +for src in ../../../../${common}/src/*.c; do + case "$(basename "${src}")" in + tx_misra.c) continue ;; + esac + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "$(basename "${src%.c}").o" +done + +"${AR}" -rcs tx.a ./*.o +rm -f ./*.o + +echo "Done: $(basename "$(pwd)")/tx.a" diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..94248a88 --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,109 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the sample image for the AArch64 port this script sits in. Run +# build_threadx.sh first, which produces tx.a. +# +# ./build_threadx_sample.sh +# TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +# +# The sample targets a fixed virtual platform: a GICv3 interrupt controller and +# an SP804 timer at the Base platform addresses. It is not expected to run on +# other models or on hardware without changing those addresses. + +set -eu + +cd "$(dirname "$(realpath "$0")")" + +core="$(basename "$(cd ../.. && pwd)")" +case "${core}" in + *_smp) cpu="${core%_smp}"; common="common_smp" ;; + *) cpu="${core}"; common="common" ;; +esac +cpu="${cpu//_/-}" + +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="aarch64-none-elf-gcc" + TARGET_FLAGS="" + # rdimon supplies the semihosting syscalls and, with them, the real + # initialise_monitor_handles that startup.S calls. + SYSCALL_LIB="--specs=rdimon.specs" + SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=aarch64-none-elf" + SYSCALL_LIB="-lsemihost" + # picolibc has no initialise_monitor_handles, and neither does the + # toolchain's semihosting library, so the weak stub stands in for it. + SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" + ;; + *) + echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 + exit 1 + ;; +esac + +CFLAGS="-g -mcpu=${cpu} -I../../../../${common}/inc -I../inc -Isample_threadx" + +echo "Building the sample for ${cpu} with ${TOOLCHAIN}" + +objects="" +for src in sample_threadx/startup.S sample_threadx/vectors.S \ + sample_threadx/v8_aarch64.S sample_threadx/v8_utils.S \ + sample_threadx/MP_Mutexes.S ${SEMIHOST_STUB} \ + sample_threadx/GICv3_gicd.c sample_threadx/GICv3_gicr.c \ + sample_threadx/sp804_timer.c sample_threadx/timer_interrupts.c \ + sample_threadx/sample_threadx.c; do + [ -n "${src}" ] || continue + obj="$(basename "${src}")" + obj="${obj%.*}.o" + "${CC}" ${TARGET_FLAGS} -c ${CFLAGS} "${src}" -o "${obj}" + objects="${objects} ${obj}" +done + +"${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ + -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ + -o sample_threadx.out -Wl,-Map=sample_threadx.map \ + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} + +rm -f ${objects} + +echo "Done: $(basename "$(pwd)")/sample_threadx.out" diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/readme.md b/ports_smp/cortex_a78_smp/gnu/example_build/readme.md new file mode 100644 index 00000000..3c52a7da --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/example_build/readme.md @@ -0,0 +1,39 @@ +# AArch64 GNU example build + +Builds the ThreadX library and a sample image for the AArch64 port this +directory belongs to. + +```sh +./build_threadx.sh # the ThreadX library, tx.a +./build_threadx_sample.sh # the sample image, sample_threadx.out +``` + +Set `TOOLCHAIN=atfe` to build with Arm Toolchain for Embedded, which is LLVM +based, instead of the GNU toolchain: + +```sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx.sh +TOOLCHAIN=atfe ATFE_CLANG=/path/to/clang ./build_threadx_sample.sh +``` + +Both scripts derive the `-mcpu` value and the kernel source directory from the +port directory they sit in, so one pair of scripts serves every AArch64 port, +SMP included. Before they existed these examples could only be built through the +Arm Development Studio project files beside them, which is why the `.cproject` +and `.launch` files remain. + +## What the sample targets + +A fixed virtual platform: a GICv3 interrupt controller and an SP804 timer at the +Base platform addresses, as set up by `startup.S`, `vectors.S` and the GICv3 +sources here. It will not run on a model or board that places those peripherals +elsewhere without changing the addresses. + +## Semihosting + +`startup.S` calls `initialise_monitor_handles` to open the standard file handles +over a debugger connection. The GNU toolchain provides it in libgloss, pulled in +by `--specs=rdimon.specs`. picolibc, which Arm Toolchain for Embedded ships, has +no equivalent and neither does its semihosting library, so `semihost_stub.S` +supplies a weak no-op for that toolchain only. A real definition always wins +over it. diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch index d583631e..baa98e1c 100644 --- a/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ <listEntry value="element formatter"/> <listEntry value="Character"/> </listAttribute> - <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView"> - <listEntry value="NODE CACHE VERSION 1"/> - <listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/> - <listEntry value="1"/> - <listEntry value="formatter"/> - <listEntry value="Hexadecimal"/> - </listAttribute> <booleanAttribute key="VFS_ENABLED" value="true"/> <stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/> <stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/> @@ -345,13 +338,13 @@ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges"> <listEntry value="100"/> </listAttribute> - <stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/> + <stringAttribute key="config_db_activity_name" value="Cortex-A78x4 SMP"/> <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/> <stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/> - <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A35x4"/> + <stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A78x4"/> <stringAttribute key="config_db_project_type" value="Bare Metal Debug"/> <stringAttribute key="config_db_project_type_id" value="BARE_METAL"/> - <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/> + <stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a78x4"/> <stringAttribute key="config_file" value="CDB://iris_config.xml"/> <booleanAttribute key="connectOnly" value="false"/> <stringAttribute key="connect_existing_model" value="false"/> @@ -424,22 +417,10 @@ <stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/> <booleanAttribute key="runAfterConnect" value="false"/> <stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/> - <mapAttribute key="scripts_view_script_links"> - <mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\gnu\example_build\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_arm\threadx\sample_threadx\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspace_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - <mapEntry key="D:\Documents\work\get_threadx-smp_cortex-a53_gnu_working\threadx_official_workspaces_no_sevice_packs\threadx\common\use_model_semihosting.ds" value=""/> - </mapAttribute> <listAttribute key="setup"> <listEntry value="CDB://Scripts/rtsm_launcher.py"/> - <listEntry value=""FVP_Base_Cortex-A35x4""/> + <listEntry value=""FVP_Base_Cortex-A78x4""/> </listAttribute> <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/> - <stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>/tmp/dgboter/bbs/dsggnu-vm-1-x86_64--mingw32-i686/buildbot/mingw32-i686--aarch64-elf/build/src/newlib-cygwin/libgloss/aarch64/</ta> 		<tb>D:\Documents\work\toolchains\newlib-cygwin\libgloss\aarch64\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/> <stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/> </launchConfiguration> diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/semihost_stub.S b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/semihost_stub.S new file mode 100644 index 00000000..c456875d --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/semihost_stub.S @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ARMv8-A example semihosting stub */ +/** */ +/**************************************************************************/ + +/* startup.S calls initialise_monitor_handles to open the standard file handles + over a debugger connection. The GNU toolchain provides it in libgloss, which + --specs=rdimon.specs pulls in, so this file is linked only for the LLVM + toolchain: picolibc has no equivalent, and neither does the toolchain's own + semihosting library, so without it the sample does not link at all. + + The definition is weak, so a real one always wins if something provides it. + The sample writes nothing to the standard handles, so doing nothing here + costs it no output. */ + + .text + .balign 4 + + .weak initialise_monitor_handles + .type initialise_monitor_handles, %function +initialise_monitor_handles: + ret + .size initialise_monitor_handles, . - initialise_monitor_handles + + .end diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/tx/.cproject b/ports_smp/cortex_a78_smp/gnu/example_build/tx/.cproject index 11d7c2fe..e3f31405 100644 --- a/ports_smp/cortex_a78_smp/gnu/example_build/tx/.cproject +++ b/ports_smp/cortex_a78_smp/gnu/example_build/tx/.cproject @@ -129,9 +129,15 @@ </folderInfo> + <fileInfo id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.config.exe.debug.var.gcc-8.3.0-aarch64-elf.794347674.1482422597" name="tx_misra.c" rcbsApplicability="disable" resourcePath="src_generic/tx_misra.c" toolsToInvoke="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701.1451532610"> + + <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701.1451532610" name="GCC C Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1247168701"/> + + </fileInfo> + <sourceEntries> - <entry excluding="src_generic/tx_misra.c|src_generic/tx_thread_timeout.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> </sourceEntries> diff --git a/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h index e97d78d5..38c86cb2 100644 --- a/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_initialize_low_level.S b/ports_smp/cortex_a78_smp/gnu/src/tx_initialize_low_level.S index 43d87225..efb08b80 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_initialize_low_level.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_initialize_low_level.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_initialize_low_level ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_restore.S index e2c48868..5cd7a9df 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_restore.S @@ -19,10 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - - -/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -207,74 +206,6 @@ __tx_thread_no_preempt_restore: // { __tx_thread_preempt_restore: - /* Was the thread being preempted waiting for the lock? */ - // if (_tx_thread_smp_protect_wait_counts[this_core] != 0) - // { - - LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list - LDR w3, [x2, x8, LSL #2] // Load waiting value for this core - CMP w3, #0 - BEQ _nobody_waiting_for_lock // Is the core waiting for the lock? - - /* Do we not have the lock? This means the ISR never got the inter-core lock. */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) - // { - - LDR x2, =_tx_thread_smp_protection // Load address of protection structure - LDR w3, [x2, #4] // Pickup the owning core - CMP w8, w3 // Compare our core to the owning core - BEQ _this_core_has_lock // Do we have the lock? - - /* We don't have the lock. This core should be in the list. Remove it. */ - // _tx_thread_smp_protect_wait_list_remove(this_core); - - _tx_thread_smp_protect_wait_list_remove // Call macro to remove core from the list - B _nobody_waiting_for_lock // Leave - - // } - // else - // { - /* We have the lock. This means the ISR got the inter-core lock, but - never released it because it saw that there was someone waiting. - Note this core is not in the list. */ - -_this_core_has_lock: - - /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ - // _tx_thread_smp_protect_wait_counts[core]--; - - LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list - LDR w3, [x2, x8, LSL #2] // Load waiting value for this core - SUB w3, w3, #1 // Decrement waiting value. Should be zero now - STR w3, [x2, x8, LSL #2] // Store new waiting value - - /* Now release the inter-core lock. */ - - /* Set protected core as invalid. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; - - LDR x2, =_tx_thread_smp_protection // Load address of protection structure - MOV w3, #0xFFFFFFFF // Build invalid value - STR w3, [x2, #4] // Mark the protected core as invalid - DMB ISH // Ensure that accesses to shared resource have completed - - /* Release protection. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; - - MOV w3, #0 // Build release protection value - STR w3, [x2, #0] // Release the protection - DSB ISH // To ensure update of the protection occurs before other CPUs awake - - /* Wake up waiting processors. Note interrupts are already enabled. */ - -#ifdef TX_ENABLE_WFE - SEV // Send event to other CPUs -#endif - - // } - // } - -_nobody_waiting_for_lock: LDR x4, [x0, #8] // Switch to thread stack pointer MOV sp, x4 // @@ -348,6 +279,7 @@ __tx_thread_dont_save_ts: /* Set bit indicating this thread is ready for execution. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x2, #1 // Build ready flag STR w2, [x0, #260] // Set thread's ready flag DMB ISH // Ensure that accesses to shared resource have completed diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_save.S index f43809f5..76641067 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_context_save.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_context_save ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_control.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_control.S index d4235180..21ec2dd1 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_control.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_control.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_disable.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_disable.S index 08f0e7e1..af2ef874 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_disable.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_disable.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_disable ARMv8-A */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_restore.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_restore.S index d0191c32..3e0780d0 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_restore.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_interrupt_restore.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_interrupt_restore ARMv8-A-SMP */ -/* 6.1.10 */ +/* _tx_thread_interrupt_restore ARMv8-A */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_schedule.S index 782491cc..de6b70dd 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_schedule.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_schedule ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -156,7 +158,7 @@ _tx_thread_ready_for_execution: LDR x2, =_tx_thread_current_ptr // Pickup address of current thread STR x0, [x2, x20, LSL #3] // Setup current thread pointer - + DMB ISH LDR x1, [x1, x20, LSL #3] // Reload the execute pointer CMP w0, w1 // Did it change? BEQ _execute_pointer_did_not_change // If not, skip handling diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_get.S index 4ffb8cc6..ea14c901 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_preempt.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_preempt.S index 8dc6933c..1d28907f 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_preempt.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_core_preempt.S @@ -19,6 +19,11 @@ /** */ /**************************************************************************/ /**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#define ICC_SGI1R_EL1 S3_0_C12_C11_5 .text @@ -27,8 +32,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_core_preempt Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_core_preempt ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_state_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_state_get.S index edae94d5..707b41d2 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_state_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_state_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_state_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_state_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_thread_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_thread_get.S index dd740e05..6c4bc9af 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_thread_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_current_thread_get.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_current_thread_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_current_thread_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_initialize_wait.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_initialize_wait.S index 985136b5..defd791c 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_initialize_wait.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_initialize_wait.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_initialize_wait Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_initialize_wait ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_low_level_initialize.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_low_level_initialize.S index 64b854d0..99b20d24 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_low_level_initialize.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_low_level_initialize.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_low_level_initialize Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_low_level_initialize ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_protect.S index 30a43701..1155a3fa 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_protect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif /* Include macros for modifying the wait list. */ #include "tx_thread_smp_protection_wait_list_macros.h" @@ -31,8 +33,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_protect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -71,293 +73,49 @@ _tx_thread_smp_protect: /* Pickup the CPU ID. */ - MRS x1, MPIDR_EL1 // Pickup the core ID + MRS x2, MPIDR_EL1 // Pickup the core ID #ifdef TX_ARMV8_2 #if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #16, #8 // Isolate cluster ID + UBFX x7, x2, #16, #8 // Isolate cluster ID #endif - UBFX x1, x1, #8, #8 // Isolate core ID + UBFX x2, x2, #8, #8 // Isolate core ID #else #if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #8, #8 // Isolate cluster ID + UBFX x7, x2, #8, #8 // Isolate cluster ID #endif - UBFX x1, x1, #0, #8 // Isolate core ID + UBFX x2, x2, #0, #8 // Isolate core ID #endif #if TX_THREAD_SMP_CLUSTERS > 1 - ADDS x1, x1, x7, LSL #2 // Calculate CPU ID + ADDS x2, x2, x7, LSL #2 // Calculate CPU ID #endif - /* Do we already have protection? */ - // if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) - // { - - LDR x2, =_tx_thread_smp_protection // Build address to protection structure - LDR w3, [x2, #4] // Pickup the owning core - CMP w1, w3 // Is it not this core? - BNE _protection_not_owned // No, the protection is not already owned - - /* We already have protection. */ - - /* Increment the protection count. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_count++; - - LDR w3, [x2, #8] // Pickup ownership count - ADD w3, w3, #1 // Increment ownership count - STR w3, [x2, #8] // Store ownership count - DMB ISH - - B _return - -_protection_not_owned: - - /* Is the lock available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _start_waiting // No, protection not available - - /* Is the list empty? */ - // if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head - LDR w3, [x3] - LDR x4, =_tx_thread_smp_protect_wait_list_tail - LDR w4, [x4] - CMP w3, w4 - BNE _list_not_empty - - /* Try to get the lock. */ - // if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) - // { - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _start_waiting // Did it fail? - - /* We got the lock! */ - // _tx_thread_smp_protect_lock_got(); - - DMB ISH // Ensure write to protection finishes - _tx_thread_smp_protect_lock_got // Call the lock got function - - B _return - -_list_not_empty: - - /* Are we at the front of the list? */ - // if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head - LDR w3, [x3] // Get the value of the head - LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list - LDR w4, [x4, x3, LSL #2] // Get the value at the head index - - CMP w1, w4 - BNE _start_waiting - - /* Is the lock still available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _start_waiting // No, protection not available - - /* Get the lock. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _start_waiting // Did it fail? - DMB ISH // - - /* Got the lock. */ - // _tx_thread_smp_protect_lock_got(); - - _tx_thread_smp_protect_lock_got - - /* Remove this core from the wait list. */ - // _tx_thread_smp_protect_remove_from_front_of_list(); - - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: - - /* For one reason or another, we didn't get the lock. */ - - /* Increment wait count. */ - // _tx_thread_smp_protect_wait_counts[this_core]++; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - ADD w4, w4, #1 // Increment wait value - STR w4, [x3, x1, LSL #2] // Store new wait value - - /* Have we not added ourselves to the list yet? */ - // if (_tx_thread_smp_protect_wait_counts[this_core] == 1) - // { - - CMP w4, #1 - BNE _already_in_list0 // Is this core already waiting? - - /* Add ourselves to the list. */ - // _tx_thread_smp_protect_wait_list_add(this_core); - - _tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list - - // } - -_already_in_list0: - - /* Restore interrupts. */ + LDR x1, =_tx_thread_smp_protection // Build address to protection structure + LDR w3, [x1, #4] // Pickup the owning core + CMP w3, w2 // Is it this core? + BEQ _owned // Yes, the protection is already owned + LDAXR w4, [x1, #0] // Pickup the protection flag + CBZ w4, _get_protection // Yes, get the protection MSR DAIF, x0 // Restore interrupts ISB // #ifdef TX_ENABLE_WFE WFE // Go into standby #endif + B _tx_thread_smp_protect // On waking, restart the protection attempt - /* We do this until we have the lock. */ - // while (1) - // { - -_try_to_get_lock: - - /* Disable interrupts so we don't get preempted. */ - - MRS x0, DAIF // Pickup current interrupt posture - MSR DAIFSet, 0x3 // Lockout interrupts - - /* Pickup the CPU ID. */ - - MRS x1, MPIDR_EL1 // Pickup the core ID -#ifdef TX_ARMV8_2 -#if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #16, #8 // Isolate cluster ID -#endif - UBFX x1, x1, #8, #8 // Isolate core ID -#else -#if TX_THREAD_SMP_CLUSTERS > 1 - UBFX x7, x1, #8, #8 // Isolate cluster ID -#endif - UBFX x1, x1, #0, #8 // Isolate core ID -#endif -#if TX_THREAD_SMP_CLUSTERS > 1 - ADDS x1, x1, x7, LSL #2 // Calculate CPU ID -#endif - - /* Do we already have protection? */ - // if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) - // { - - LDR w3, [x2, #4] // Pickup the owning core - CMP w3, w1 // Is it this core? - BEQ _got_lock_after_waiting // Yes, the protection is already owned. This means - // an ISR preempted us and got protection - - // } - - /* Are we at the front of the list? */ - // if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) - // { - - LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head - LDR w3, [x3] // Get the value of the head - LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list - LDR w4, [x4, x3, LSL #2] // Get the value at the head index - - CMP w1, w4 - BNE _did_not_get_lock - - /* Is the lock still available? */ - // if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) - // { - - LDAXR w3, [x2, #0] // Pickup the protection flag - CMP w3, #0 - BNE _did_not_get_lock // No, protection not available - - /* Get the lock. */ - // _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; - - MOV w3, #1 // Build lock value - STXR w4, w3, [x2, #0] // Attempt to get the protection - CMP w4, #0 - BNE _did_not_get_lock // Did it fail? - DMB ISH // - - /* Got the lock. */ - // _tx_thread_smp_protect_lock_got(); - - _tx_thread_smp_protect_lock_got - - /* Remove this core from the wait list. */ - // _tx_thread_smp_protect_remove_from_front_of_list(); - - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting - -_did_not_get_lock: - - /* For one reason or another, we didn't get the lock. */ - - /* Were we removed from the list? This can happen if we're a thread - and we got preempted. */ - // if (_tx_thread_smp_protect_wait_counts[this_core] == 0) - // { - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - CMP w4, #0 - BNE _already_in_list1 // Is this core already in the list? - - /* Add ourselves to the list. */ - // _tx_thread_smp_protect_wait_list_add(this_core); - - _tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list - - /* Our waiting count was also reset when we were preempted. Increment it again. */ - // _tx_thread_smp_protect_wait_counts[this_core]++; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts - LDR w4, [x3, x1, LSL #2] // Load waiting value for this core - ADD w4, w4, #1 // Increment wait value - STR w4, [x3, x1, LSL #2] // Store new wait value value - - // } - -_already_in_list1: - - /* Restore interrupts and try again. */ - +_get_protection: + MOV x4, #1 // Build lock value + STXR w5, w4, [x1] // Attempt to get the protection + CBZ w5, _got_protection // Did it succeed? w5 = 0 means success! MSR DAIF, x0 // Restore interrupts - ISB // -#ifdef TX_ENABLE_WFE - WFE // Go into standby -#endif - B _try_to_get_lock // On waking, restart the protection attempt - -_got_lock_after_waiting: - - /* We're no longer waiting. */ - // _tx_thread_smp_protect_wait_counts[this_core]--; - - LDR x3, =_tx_thread_smp_protect_wait_counts // Load waiting list - LDR w4, [x3, x1, LSL #2] // Load current wait value - SUB w4, w4, #1 // Decrement wait value - STR w4, [x3, x1, LSL #2] // Store new wait value value - - /* Restore registers and return. */ - -_return: + B _tx_thread_smp_protect // Restart the protection attempt +_got_protection: + DMB ISH // + STR w2, [x1, #4] // Save owning core +_owned: + LDR w5, [x1, #8] // Pickup ownership count + ADD w5, w5, #1 // Increment ownership count + STR w5, [x1, #8] // Store ownership count + DMB ISH // RET diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S index f3045738..4bb9f1cb 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -19,7 +20,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +30,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_time_get Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_time_get ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -58,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_unprotect.S index 49af176a..680e8bc8 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_unprotect.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -27,8 +29,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */ -/* 6.1.10 */ +/* _tx_thread_smp_unprotect ARMv8-A-SMP */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -96,11 +98,6 @@ _tx_thread_smp_unprotect: CMP w3, #0 // Is the preempt disable flag set? BNE _still_protected // Yes, skip the protection release - LDR x2,=_tx_thread_smp_protect_wait_counts // Build build address of wait counts - LDR w3, [x2, x1, LSL #2] // Pickup wait list value - CMP w3, #0 // Are any entities on this core waiting? - BNE _still_protected // Yes, skip the protection release - LDR x2,=_tx_thread_smp_protection // Build address of protection structure MOV w3, #0xFFFFFFFF // Build invalid value STR w3, [x2, #4] // Mark the protected core as invalid diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_stack_build.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_stack_build.S index fa11a65c..581e259e 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_stack_build.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_stack_build.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_stack_build ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_system_return.S index 4eebb9aa..23c75241 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_system_return.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_system_return ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ @@ -159,6 +161,7 @@ __tx_thread_dont_save_ts: /* Set ready bit in thread control block. */ + DMB ISH // Ensure that accesses to shared resource have completed MOV x3, #1 // Build ready value STR w3, [x6, #260] // Make the thread ready DMB ISH // diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_timer_interrupt.S b/ports_smp/cortex_a78_smp/gnu/src/tx_timer_interrupt.S index 6f90e5d1..5c6a6bc2 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_timer_interrupt.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_timer_interrupt.S @@ -19,7 +19,9 @@ /** */ /**************************************************************************/ /**************************************************************************/ - +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif .text .align 3 @@ -28,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_timer_interrupt ARMv8-A-SMP */ -/* 6.1.10 */ +/* 6.3.0 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ diff --git a/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h index c5af63c8..80762931 100644 --- a/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h @@ -388,7 +388,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s index 78ddfee1..de76d8e6 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -195,76 +190,6 @@ __tx_thread_no_preempt_restore ; else ; { __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s index acc2de11..289c0ea1 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s index 1ced36e9..8ac992cd 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -163,6 +166,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s index 5cc9f04e..48cce36f 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -29,17 +31,9 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" */ -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -81,11 +75,9 @@ _tx_thread_smp_protect ;VOID _tx_thread_smp_protect(VOID) ;{ ; - PUSH {r4-r6} ; Save registers we'll be using -; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -93,266 +85,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -360,4 +179,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f7581458..00000000 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,312 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r10 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r10, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r10, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s index 627d36f3..c63f6cc5 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -68,8 +70,7 @@ EXPORT _tx_thread_smp_time_get _tx_thread_smp_time_get - MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + MRRC p15, 0, r0, r1, c14 ; Read generic timer physical count IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +79,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s index 260d13dc..f132cb40 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s index ebd80ae2..84c8e036 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s index 86145e1e..2d4b34a1 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..d4094f4d --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX port sources for cortex_a7_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..2f27e278 --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A7 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..c3475fab --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,54 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A7 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" + # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a7 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a7 -nostartfiles \ + -T sample_threadx.ld \ + ${SYSCALL_LIB} \ + ${ENTRY_FLAG} \ + -o sample_threadx.out \ + MP_GIC.o MP_Mutexes.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S new file mode 100644 index 00000000..abc817d5 --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 diff --git a/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h index 93b89ff9..31725d3e 100644 --- a/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S index 94e85ad3..b11e23ab 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -28,8 +30,6 @@ @#include "tx_api.h" @#include "tx_thread.h" @#include "tx_timer.h" -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .arm @@ -50,11 +50,6 @@ IRQ_MODE = 0x92 @ Disable IRQ, IRQ mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -200,76 +195,6 @@ __tx_thread_no_preempt_restore: @ else @ { __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S index 448b3a5a..75a63ed4 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -150,11 +152,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S index 88917752..a9e12749 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -180,6 +183,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S index 4404585d..74dff802 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -29,17 +31,9 @@ @#include "tx_thread.h" @#include "tx_timer.h" */ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -83,11 +77,9 @@ _tx_thread_smp_protect: @VOID _tx_thread_smp_protect(VOID) @{ @ - PUSH {r4-r6} @ Save registers we'll be using -@ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -95,266 +87,93 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2, #0] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ -@ /* Restore interrupts. */ -@ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got +_got_protection: @ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_remove_from_front_of_list + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core - B _got_lock_after_waiting - -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index dff747d1..00000000 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,308 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r10 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r10, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r10, LSL #2] @ Store new waiting value - - .endm - diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S index 067f50d8..e869c0e7 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -70,8 +72,7 @@ .type _tx_thread_smp_time_get,function _tx_thread_smp_time_get: - MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + MRRC p15, 0, r0, r1, c14 @ Read generic timer physical count #ifdef __THUMB_INTERWORK BX lr @ Return to caller @@ -79,4 +80,3 @@ _tx_thread_smp_time_get: MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S index 5b939a05..66c6689c 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S index 98e64ad1..7beaf661 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S index 0d8aab55..ee9ca1c7 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h index 1f2ab286..b36a314f 100644 --- a/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h @@ -393,7 +393,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/AC5 Version Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/AC5 Version Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s index b6c179cd..4451091b 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore ; { ; __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; - MOV r0, r10 ; Move the core ID to r0 for the macro -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s index a0e2a5e6..9c047716 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s index 63e7492c..45298ff3 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -163,6 +166,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s index 1f2330d9..fe92cb92 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -31,17 +33,9 @@ ; ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -83,11 +77,9 @@ _tx_thread_smp_protect ;VOID _tx_thread_smp_protect(VOID) ;{ ; - PUSH {r4-r6} ; Save registers we'll be using -; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -95,266 +87,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -362,4 +181,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index fec51581..00000000 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,314 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r0 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register - AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r0, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r0, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s index 5b67b283..9da21821 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -69,7 +71,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + LDR r0, [r0, #0x200] ; Read global timer count low register IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +80,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s index ed3fae48..1b4b963a 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026 Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s index f03fc6fe..485b0131 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s index 8102e78b..26acf6e4 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt index 4b13e1a1..dd2c1a41 100644 --- a/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 00000000..8050c775 --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A9 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 00000000..42987622 --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,54 @@ +#!/bin/sh +############################################################################## +# Copyright (c) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# SPDX-License-Identifier: MIT +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A9 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a9 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_SCU.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_PrivateTimer.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a9 -nostartfiles \ + -T sample_threadx.ld \ + ${ENTRY_FLAG} \ + ${SYSCALL_LIB} \ + -o sample_threadx.out MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S new file mode 100644 index 00000000..abc817d5 --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 diff --git a/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h index c43fcb7a..56497057 100644 --- a/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/GNU Version Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/GNU Version Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S index 2fbf25fd..c09d258d 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -29,8 +31,6 @@ @#include "tx_thread.h" @#include "tx_timer.h" @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" #ifdef TX_ENABLE_FIQ_SUPPORT DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore: @ { @ __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - MOV r0, r10 @ Move the core ID to r0 for the macro - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S index ae4065c4..2cef910d 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -147,11 +149,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S index 84fec67d..3e8a41e6 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -165,6 +168,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S index e90f73e2..9a3838f1 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -31,17 +33,9 @@ @ @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -85,11 +79,9 @@ _tx_thread_smp_protect: @VOID _tx_thread_smp_protect(VOID) @{ @ - PUSH {r4-r6} @ Save registers we'll be using -@ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -97,270 +89,96 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2, #0] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: -@ -@ /* Restore interrupts. */ +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ +_got_protection: @ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f1ad80e8..00000000 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,309 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r0 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - MRC p15, 0, r0, c0, c0, 5 @ Read CPU ID register - AND r0, r0, #0x03 @ Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r0, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r0, LSL #2] @ Store new waiting value - .endm - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S index 9cebe0f2..55215b1e 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -71,12 +73,10 @@ _tx_thread_smp_time_get: MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + LDR r0, [r0, #0x200] @ Read global timer count low register #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S index a76677ec..c4f42dec 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026 Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S index 6feec05b..02738e90 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S index 5991c470..f887de91 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h index cc17a732..10743d13 100644 --- a/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h @@ -393,7 +393,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-R SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-R SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s index 780a6b0a..9ce969e2 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -134,11 +135,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save // If so, interrupt occurred in // scheduling loop - nothing needs saving! - /* Save the current stack pointer in the thread's control block. */ - // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - - /* Switch to the system stack. */ - // sp = _tx_thread_system_stack_ptr; + /* This routine runs in IRQ mode on this core's banked IRQ stack, which + serves as the system stack on this architecture, so there is no stack + switch to perform here. The thread's stack pointer is saved in its + control block by _tx_thread_context_restore, and only when the + interrupt results in preemption. */ MOV r10, #0 // Clear stack limit diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s index a43484d7..11f7f4ff 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -57,7 +58,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 // Read periph base address - LDR r0, [r0, #0x604] // Read count register + LDR r0, [r0, #0x200] // Read global timer count low register IF {INTER} = {TRUE} BX lr // Return to caller diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s index 2280a351..935d88fa 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -120,9 +121,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 // Build index into time-slice array LDR r1, [r2, #0] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread's control block. The + scheduler runs on this core's banked SVC mode stack, which the startup + code set up, so there is no stack switch to perform. */ // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - // sp = _tx_thread_system_stack_ptr[core]; STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s index c62297e8..dfbe9bc2 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -132,11 +133,11 @@ __tx_thread_not_nested_save /* Note: Minimal context of interrupted thread is already saved. */ - /* Save the current stack pointer in the thread's control block. */ - // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - - /* Switch to the system stack. */ - // sp = _tx_thread_system_stack_ptr[core]; + /* This routine runs in IRQ mode on this core's banked IRQ stack, which + serves as the system stack on this architecture, so there is no stack + switch to perform here. The thread's stack pointer is saved in its + control block by _tx_thread_context_restore, and only when the + interrupt results in preemption. */ MOV r10, #0 // Clear stack limit diff --git a/ports_smp/linux/gnu/CMakeLists.txt b/ports_smp/linux/gnu/CMakeLists.txt new file mode 100644 index 00000000..7ff9e0a5 --- /dev/null +++ b/ports_smp/linux/gnu/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX port sources for linux, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) + +# The demo program beside the port. Off by default so the ordinary build +# produces just the library; -DTHREADX_SAMPLE=ON adds the sample_threadx target. +option(THREADX_SAMPLE "Build the sample program for this port" OFF) +if(THREADX_SAMPLE) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build) +endif() diff --git a/ports_smp/linux/gnu/example_build/CMakeLists.txt b/ports_smp/linux/gnu/example_build/CMakeLists.txt new file mode 100644 index 00000000..90d4078a --- /dev/null +++ b/ports_smp/linux/gnu/example_build/CMakeLists.txt @@ -0,0 +1,17 @@ +# Build the sample_threadx program that ports/linux/gnu/Makefile builds, so the +# CMake build can produce a runnable demo rather than only the library. +# +# Guarded by THREADX_SAMPLE in the parent so the default build stays a pure +# library build. + +add_executable(sample_threadx) + +target_sources(sample_threadx PRIVATE ${CMAKE_CURRENT_LIST_DIR}/sample_threadx.c) + +target_include_directories(sample_threadx + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../inc + ${CMAKE_CURRENT_LIST_DIR}/../../../../${TX_COMMON_DIR}/inc +) + +target_link_libraries(sample_threadx PRIVATE threadx) diff --git a/ports_smp/linux/gnu/inc/tx_port.h b/ports_smp/linux/gnu/inc/tx_port.h index bb1021dd..b7da882a 100644 --- a/ports_smp/linux/gnu/inc/tx_port.h +++ b/ports_smp/linux/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -373,13 +375,21 @@ void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long lin */ -#ifndef TX_MISRA_ENABLE +/* The clock below is read for every trace event in both builds. The MISRA form + of the in-line insert takes the time stamp as an argument rather than reading + it itself, so the macro has to be an expression; that is why it carries no + trailing semicolon. */ + #ifndef TX_TRACE_TIME_SOURCE #define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec)) #endif -#else + +/* Declared here rather than used: this port supplies its own time stamp above, + but the generic definition in common_smp/src/tx_misra.c is compiled for this + port and needs a declaration in scope. */ + +#ifdef TX_MISRA_ENABLE ULONG _tx_misra_time_stamp_get(VOID); -#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() #endif #ifndef TX_TRACE_TIME_MASK @@ -503,6 +513,16 @@ typedef struct } TX_LINUX_MUTEX; +/* Define how long a thread waits on the Linux mutex before retrying. A thread + parked on the mutex can be suspended by the port's signal handler and so never + act on the wake-up the next release sends it, which leaves the wake-up lost + and every other waiter parked on a mutex that is free. */ + +#ifndef TX_LINUX_MUTEX_RETRY_NSEC +#define TX_LINUX_MUTEX_RETRY_NSEC 1000000 +#endif + + /* Define Linux-specific critical section APIs. */ void _tx_linux_mutex_obtain(TX_LINUX_MUTEX *mutex); @@ -622,7 +642,7 @@ void _tx_thread_smp_debug_entry_insert(ULONG id, ULONG su #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Linux/gcc Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Linux/gcc Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/linux/gnu/src/tx_thread_schedule.c b/ports_smp/linux/gnu/src/tx_thread_schedule.c index 0c3e8e32..0b6eba25 100644 --- a/ports_smp/linux/gnu/src/tx_thread_schedule.c +++ b/ports_smp/linux/gnu/src/tx_thread_schedule.c @@ -292,6 +292,8 @@ void _tx_linux_mutex_obtain(TX_LINUX_MUTEX *mutex) TX_THREAD *thread_ptr; pthread_t current_thread_id; UINT i; +INT linux_status; +struct timespec ts; /* Pickup the current thread ID. */ current_thread_id = pthread_self(); @@ -343,8 +345,43 @@ UINT i; thread_ptr -> tx_thread_linux_mutex_access = TX_TRUE; } - /* Get the Linux mutex. */ - pthread_mutex_lock(&mutex -> tx_linux_mutex); + /* Get the Linux mutex. The wait is timed and retried rather than left + to pthread_mutex_lock, because a thread can be signalled into the + port's suspend handler while it is parked on this mutex. That handler + does not return until the thread is resumed, so the wake-up the next + release sends is delivered to a thread that never retries and is lost. + Any other thread parked on the mutex then waits on a mutex that is + free, which on this port deadlocks the whole process: the thread that + can resume the suspended one is the scheduler, and the scheduler takes + this mutex on every pass. Retrying on a timeout costs nothing when + the mutex is handed over normally, and turns that lost wake-up into a + delay of at most the retry period. */ + do + { + + /* Set the deadline for this attempt. */ + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec = ts.tv_nsec + TX_LINUX_MUTEX_RETRY_NSEC; + if (ts.tv_nsec >= 1000000000) + { + + ts.tv_nsec = ts.tv_nsec - 1000000000; + ts.tv_sec++; + } + + linux_status = pthread_mutex_timedlock(&mutex -> tx_linux_mutex, &ts); + + /* Anything but the deadline expiring is a real failure to obtain the + mutex, so stop retrying and record it. */ + if ((linux_status != 0) && (linux_status != ETIMEDOUT)) + { + + /* Increment the system error counter. */ + _tx_linux_system_error++; + break; + } + + } while (linux_status != 0); /* At this point we have the mutex. */ diff --git a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c index 7428666f..2e0e7f1e 100644 --- a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c +++ b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -124,11 +126,18 @@ pthread_t current_thread_id; _tx_linux_debug_entry_insert("UNPROTECT-nested", __FILE__, __LINE__); } - /* Only release the critical section. */ - _tx_linux_mutex_release(&_tx_linux_mutex); } - /* Release the critical section. */ + /* Release the critical section taken by the matching _tx_thread_smp_protect. + The protection and the critical section are separate counts, and this + release is owed whether or not the protection still names this core: the + protection can be cleared by another core while this one holds the + critical section it took. The critical section is only handed back to + Linux when its nesting count reaches zero, so a release skipped here is + never made up and the mutex stays locked for the life of the process. */ + _tx_linux_mutex_release(&_tx_linux_mutex); + + /* Release the critical section taken on entry. */ _tx_linux_mutex_release(&_tx_linux_mutex); } diff --git a/ports_smp/linux/gnu/src/tx_thread_stack_build.c b/ports_smp/linux/gnu/src/tx_thread_stack_build.c index 1b491a3a..65b8e25c 100644 --- a/ports_smp/linux/gnu/src/tx_thread_stack_build.c +++ b/ports_smp/linux/gnu/src/tx_thread_stack_build.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -80,6 +82,7 @@ void *_tx_linux_thread_entry(void *ptr); /**************************************************************************/ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) { +ALIGN_TYPE fake_stack_ptr; struct sched_param sp; pthread_attr_t attrs; @@ -120,8 +123,13 @@ pthread_attr_t attrs; tx_interrupt_control nesting. */ thread_ptr -> tx_thread_linux_mutex_access = TX_FALSE; - /* Setup a fake thread stack pointer. */ - thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + /* Setup a fake thread stack pointer. The stack end points at the last byte of the + thread's stack area and is therefore not necessarily aligned, so round the result + down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is + also the starting value of the stack checking logic's highest used pointer. */ + fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8)); + fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); + thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt new file mode 100644 index 00000000..c54890aa --- /dev/null +++ b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. +# +# ThreadX port sources for mips32_interaptiv_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h b/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h index 87ee3fcc..6e15542c 100644 --- a/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h +++ b/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h @@ -419,7 +419,7 @@ THREAD_SMP_DECLARE ULONG _tx_thread_smp_initial_fpu_control_register; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h b/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h index 06d0142e..20b1d56b 100644 --- a/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h +++ b/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h @@ -509,7 +509,7 @@ THREAD_SMP_DECLARE ULONG _tx_thread_smp_initial_fpu_control_register; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/win64/vs_2022/CMakeLists.txt b/ports_smp/win64/vs_2022/CMakeLists.txt index 982f9684..447a0026 100644 --- a/ports_smp/win64/vs_2022/CMakeLists.txt +++ b/ports_smp/win64/vs_2022/CMakeLists.txt @@ -23,6 +23,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/win64/vs_2022/inc/tx_port.h b/ports_smp/win64/vs_2022/inc/tx_port.h index 15225230..949c812e 100644 --- a/ports_smp/win64/vs_2022/inc/tx_port.h +++ b/ports_smp/win64/vs_2022/inc/tx_port.h @@ -441,7 +441,7 @@ UINT _tx_thread_interrupt_control(UINT new_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2026 Eclipse ThreadX contributors. * ThreadX SMP/Win64/MSVC Version 6.5.1.202602a *"; + "(c) 2026 Eclipse ThreadX contributors. * ThreadX SMP/Win64/MSVC Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c b/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c index f517fd6b..9752ec3d 100644 --- a/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c +++ b/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c b/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c index d1b74c38..1a2cd182 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_context_save.c b/ports_smp/win64/vs_2022/src/tx_thread_context_save.c index 89d6cd75..01a894c6 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_context_save.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_context_save.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_schedule.c b/ports_smp/win64/vs_2022/src/tx_thread_schedule.c index f33eb7b0..b247ee4c 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_schedule.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_schedule.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c index 2da24fda..4f0da534 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c index bf1726df..ce937b19 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c index ade6774f..1f93f8a9 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c index e59caffc..954b9e3c 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c index b845767d..ac553d66 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c b/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c index 0531fb3b..60478e7b 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_system_return.c b/ports_smp/win64/vs_2022/src/tx_thread_system_return.c index 8207f345..b7690402 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_system_return.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_system_return.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE |
