summaryrefslogtreecommitdiff
path: root/ports/cortex_a72/gnu
diff options
context:
space:
mode:
authorYuxin Zhou <[email protected]>2022-01-29 00:24:03 +0000
committerYuxin Zhou <[email protected]>2022-01-29 00:24:03 +0000
commitf7f0957188d48ec5278107dc8fbd2de747fda1b8 (patch)
treefee9f4baf5a6a8bb944c5de8ad10fda300027d26 /ports/cortex_a72/gnu
parentb216ceb25e2b6ae1ea83c1ae91d114a6fc2fc4ec (diff)
Release 6.1.10
Diffstat (limited to 'ports/cortex_a72/gnu')
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/.cproject170
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/.project26
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/GICv3.h561
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_aliases.h113
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicc.h254
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicd.c339
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicr.c308
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.S133
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.h66
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/PPM_AEM.h66
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c393
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.launch328
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.ld245
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.c122
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.h53
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/startup.S787
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/timer_interrupts.c152
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/use_model_semihosting.ds1
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.S179
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.h103
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/v8_mmu.h128
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/v8_system.h115
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/v8_utils.S69
-rw-r--r--ports/cortex_a72/gnu/example_build/sample_threadx/vectors.S252
-rw-r--r--ports/cortex_a72/gnu/example_build/tx/.cproject162
-rw-r--r--ports/cortex_a72/gnu/example_build/tx/.project48
-rw-r--r--ports/cortex_a72/gnu/inc/tx_port.h379
-rw-r--r--ports/cortex_a72/gnu/src/tx_initialize_low_level.S98
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_context_restore.S287
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_context_save.S216
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_fp_disable.c97
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_fp_enable.c96
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_interrupt_control.S81
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_interrupt_disable.S79
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_interrupt_restore.S77
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_schedule.S228
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_stack_build.S158
-rw-r--r--ports/cortex_a72/gnu/src/tx_thread_system_return.S151
-rw-r--r--ports/cortex_a72/gnu/src/tx_timer_interrupt.S228
39 files changed, 7348 insertions, 0 deletions
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/.cproject b/ports/cortex_a72/gnu/example_build/sample_threadx/.cproject
new file mode 100644
index 00000000..1c32cb32
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/.cproject
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+
+ <cconfiguration id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048">
+
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+
+ <externalSettings/>
+
+ <extensions>
+
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ </extensions>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug.base">
+
+ <folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048." name="/" resourcePath="">
+
+ <toolChain id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.33749088" name="GCC 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf">
+
+ <targetPlatform id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.33749088.1343346543" name=""/>
+
+ <builder buildPath="${workspace_loc:/sample_threadx}/Debug" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder.910370896" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder"/>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1331565505" 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">
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath.831465095" name="Include paths (-I)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath" useByScannerDiscovery="false" valueType="includePath">
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/tx/inc_generic}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/tx/inc_port}&quot;"/>
+
+ </option>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym.1613866201" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
+
+ <listOptionValue builtIn="false" value="STANDALONE"/>
+
+ </option>
+
+ <option defaultValue="gnu.c.optimization.level.none" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.1769854265" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" valueType="enumerated"/>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug.268949876" name="Debug Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug" useByScannerDiscovery="false"/>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu.1607040325" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu" useByScannerDiscovery="false" value="" valueType="string"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input.301538030" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input"/>
+
+ </tool>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf.64294854" name="GCC C++ Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf">
+
+ <option defaultValue="gnu.c.optimization.level.none" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.1835980884" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" valueType="enumerated"/>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug.788212214" name="Debug Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug" useByScannerDiscovery="false"/>
+
+ </tool>
+
+ <tool command="aarch64-elf-gcc.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf.1804365799" name="GCC Assembler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf">
+
+ <option defaultValue="true" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug.490655419" name="Generate debugging information (-g)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug" useByScannerDiscovery="false" valueType="boolean"/>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu.694327385" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu" useByScannerDiscovery="false" value="" valueType="string"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input.883450564" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input"/>
+
+ </tool>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf.891273559" name="GCC C Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf">
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libs.654731770" name="Libraries (-l)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libs" useByScannerDiscovery="false" valueType="libs">
+
+ <listOptionValue builtIn="false" value="tx"/>
+
+ </option>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libsearch.764636049" name="Library search path (-L)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libsearch" useByScannerDiscovery="false" valueType="libPaths">
+
+ <listOptionValue builtIn="false" value="&quot;..\..\tx\Debug&quot;"/>
+
+ </option>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.script.1545347593" name="Linker script" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.script" useByScannerDiscovery="false" value="..\sample_threadx.ld" valueType="string"/>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags.846498594" name="Other flags" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags" useByScannerDiscovery="false" value="--specs=rdimon.specs" valueType="string"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input.1672586300" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input">
+
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+
+ </inputType>
+
+ </tool>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf.2107716357" name="GCC C++ Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf"/>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf.1675872554" name="GCC Archiver 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf"/>
+
+ </toolChain>
+
+ </folderInfo>
+
+ <sourceEntries>
+
+ <entry excluding="startup_el3.S|startup_el2.S|startup_el1.S|startup_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+
+ </sourceEntries>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+
+ </cconfiguration>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <project id="sample_threadx.com.arm.eclipse.build.project.v6.exe.1027551600" name="Executable"/>
+
+ </storageModule>
+
+ <storageModule moduleId="scannerConfiguration">
+
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+
+ <storageModule moduleId="refreshScope" versionNumber="2">
+
+ <configuration configurationName="Debug">
+
+ <resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
+
+ </configuration>
+
+ <configuration configurationName="Release">
+
+ <resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+
+ <storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
+
+</cproject>
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/.project b/ports/cortex_a72/gnu/example_build/sample_threadx/.project
new file mode 100644
index 00000000..a1b15572
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/.project
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>sample_threadx</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+</projectDescription>
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3.h b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3.h
new file mode 100644
index 00000000..dfe37586
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3.h
@@ -0,0 +1,561 @@
+/*
+ * GICv3.h - data types and function prototypes for GICv3 utility routines
+ *
+ * Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+#ifndef GICV3_h
+#define GICV3_h
+
+#include <stdint.h>
+
+/*
+ * extra flags for GICD enable
+ */
+typedef enum
+{
+ gicdctlr_EnableGrp0 = (1 << 0),
+ gicdctlr_EnableGrp1NS = (1 << 1),
+ gicdctlr_EnableGrp1A = (1 << 1),
+ gicdctlr_EnableGrp1S = (1 << 2),
+ gicdctlr_EnableAll = (1 << 2) | (1 << 1) | (1 << 0),
+ gicdctlr_ARE_S = (1 << 4), /* Enable Secure state affinity routing */
+ gicdctlr_ARE_NS = (1 << 5), /* Enable Non-Secure state affinity routing */
+ gicdctlr_DS = (1 << 6), /* Disable Security support */
+ gicdctlr_E1NWF = (1 << 7) /* Enable "1-of-N" wakeup model */
+} GICDCTLRFlags_t;
+
+/*
+ * modes for SPI routing
+ */
+typedef enum
+{
+ gicdirouter_ModeSpecific = 0,
+ gicdirouter_ModeAny = (1 << 31)
+} GICDIROUTERBits_t;
+
+typedef enum
+{
+ gicdicfgr_Level = 0,
+ gicdicfgr_Edge = (1 << 1)
+} GICDICFGRBits_t;
+
+typedef enum
+{
+ gicigroupr_G0S = 0,
+ gicigroupr_G1NS = (1 << 0),
+ gicigroupr_G1S = (1 << 2)
+} GICIGROUPRBits_t;
+
+typedef enum
+{
+ gicrwaker_ProcessorSleep = (1 << 1),
+ gicrwaker_ChildrenAsleep = (1 << 2)
+} GICRWAKERBits_t;
+
+/**********************************************************************/
+
+/*
+ * Utility macros & functions
+ */
+#define RANGE_LIMIT(x) ((sizeof(x) / sizeof((x)[0])) - 1)
+
+static inline uint64_t gicv3PackAffinity(uint32_t aff3, uint32_t aff2,
+ uint32_t aff1, uint32_t aff0)
+{
+ /*
+ * only need to cast aff3 to get type promotion for all affinities
+ */
+ return ((((uint64_t)aff3 & 0xff) << 32) |
+ ((aff2 & 0xff) << 16) |
+ ((aff1 & 0xff) << 8) | aff0);
+}
+
+/**********************************************************************/
+
+/*
+ * GIC Distributor Function Prototypes
+ */
+
+/*
+ * ConfigGICD - configure GIC Distributor prior to enabling it
+ *
+ * Inputs:
+ *
+ * control - control flags
+ *
+ * Returns:
+ *
+ * <nothing>
+ *
+ * NOTE:
+ *
+ * ConfigGICD() will set an absolute flags value, whereas
+ * {En,Dis}ableGICD() will only {set,clear} the flag bits
+ * passed as a parameter
+ */
+void ConfigGICD(GICDCTLRFlags_t flags);
+
+/*
+ * EnableGICD - top-level enable for GIC Distributor
+ *
+ * Inputs:
+ *
+ * flags - new control flags to set
+ *
+ * Returns:
+ *
+ * <nothing>
+ *
+ * NOTE:
+ *
+ * ConfigGICD() will set an absolute flags value, whereas
+ * {En,Dis}ableGICD() will only {set,clear} the flag bits
+ * passed as a parameter
+ */
+void EnableGICD(GICDCTLRFlags_t flags);
+
+/*
+ * DisableGICD - top-level disable for GIC Distributor
+ *
+ * Inputs
+ *
+ * flags - control flags to clear
+ *
+ * Returns
+ *
+ * <nothing>
+ *
+ * NOTE:
+ *
+ * ConfigGICD() will set an absolute flags value, whereas
+ * {En,Dis}ableGICD() will only {set,clear} the flag bits
+ * passed as a parameter
+ */
+void DisableGICD(GICDCTLRFlags_t flags);
+
+/*
+ * SyncAREinGICD - synchronise GICD Address Routing Enable bits
+ *
+ * Inputs
+ *
+ * flags - absolute flag bits to set in GIC Distributor
+ *
+ * dosync - flag whether to wait for ARE bits to match passed
+ * flag field (dosync = true), or whether to set absolute
+ * flag bits (dosync = false)
+ *
+ * Returns
+ *
+ * <nothing>
+ *
+ * NOTE:
+ *
+ * This function is used to resolve a race in an MP system whereby secondary
+ * CPUs cannot reliably program all Redistributor registers until the
+ * primary CPU has enabled Address Routing. The primary CPU will call this
+ * function with dosync = false, while the secondaries will call it with
+ * dosync = true.
+ */
+void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync);
+
+/*
+ * EnableSPI - enable a specific shared peripheral interrupt
+ *
+ * Inputs:
+ *
+ * id - which interrupt to enable
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void EnableSPI(uint32_t id);
+
+/*
+ * DisableSPI - disable a specific shared peripheral interrupt
+ *
+ * Inputs:
+ *
+ * id - which interrupt to disable
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void DisableSPI(uint32_t id);
+
+/*
+ * SetSPIPriority - configure the priority for a shared peripheral interrupt
+ *
+ * Inputs:
+ *
+ * id - interrupt identifier
+ *
+ * priority - 8-bit priority to program (see note below)
+ *
+ * Returns:
+ *
+ * <nothing>
+ *
+ * Note:
+ *
+ * The GICv3 architecture makes this function sensitive to the Security
+ * context in terms of what effect it has on the programmed priority: no
+ * attempt is made to adjust for the reduced priority range available
+ * when making Non-Secure accesses to the GIC
+ */
+void SetSPIPriority(uint32_t id, uint32_t priority);
+
+/*
+ * GetSPIPriority - determine the priority for a shared peripheral interrupt
+ *
+ * Inputs:
+ *
+ * id - interrupt identifier
+ *
+ * Returns:
+ *
+ * interrupt priority in the range 0 - 0xff
+ */
+uint32_t GetSPIPriority(uint32_t id);
+
+/*
+ * SetSPIRoute - specify interrupt routing when gicdctlr_ARE is enabled
+ *
+ * Inputs:
+ *
+ * id - interrupt identifier
+ *
+ * affinity - prepacked "dotted quad" affinity routing. NOTE: use the
+ * gicv3PackAffinity() helper routine to generate this input
+ *
+ * mode - select routing mode (specific affinity, or any recipient)
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode);
+
+/*
+ * GetSPIRoute - read ARE-enabled interrupt routing information
+ *
+ * Inputs:
+ *
+ * id - interrupt identifier
+ *
+ * Returns:
+ *
+ * routing configuration
+ */
+uint64_t GetSPIRoute(uint32_t id);
+
+/*
+ * SetSPITarget - configure the set of processor targets for an interrupt
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * target - 8-bit target bitmap
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void SetSPITarget(uint32_t id, uint32_t target);
+
+/*
+ * GetSPITarget - read the set of processor targets for an interrupt
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * 8-bit target bitmap
+ */
+uint32_t GetSPITarget(uint32_t id);
+
+/*
+ * ConfigureSPI - setup an interrupt as edge- or level-triggered
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * config - desired configuration
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void ConfigureSPI(uint32_t id, GICDICFGRBits_t config);
+
+/*
+ * SetSPIPending - mark an interrupt as pending
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void SetSPIPending(uint32_t id);
+
+/*
+ * ClearSPIPending - mark an interrupt as not pending
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void ClearSPIPending(uint32_t id);
+
+/*
+ * GetSPIPending - query whether an interrupt is pending
+ *
+ * Inputs
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * pending status
+ */
+uint32_t GetSPIPending(uint32_t id);
+
+/*
+ * SetSPISecurity - mark a shared peripheral interrupt as
+ * security <group>
+ *
+ * Inputs
+ *
+ * id - which interrupt to mark
+ *
+ * group - the group for the interrupt
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group);
+
+/*
+ * SetSPISecurityBlock - mark a block of 32 shared peripheral
+ * interrupts as security <group>
+ *
+ * Inputs:
+ *
+ * block - which block to mark (e.g. 1 = Ints 32-63)
+ *
+ * group - the group for the interrupts
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group);
+
+/*
+ * SetSPISecurityAll - mark all shared peripheral interrupts
+ * as security <group>
+ *
+ * Inputs:
+ *
+ * group - the group for the interrupts
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void SetSPISecurityAll(GICIGROUPRBits_t group);
+
+/**********************************************************************/
+
+/*
+ * GIC Re-Distributor Function Prototypes
+ *
+ * The model for calling Redistributor functions is that, rather than
+ * identifying the target redistributor with every function call, the
+ * SelectRedistributor() function is used to identify which redistributor
+ * is to be used for all functions until a different redistributor is
+ * explicitly selected
+ */
+
+/*
+ * WakeupGICR - wake up a Redistributor
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to wakeup
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void WakeupGICR(uint32_t gicr);
+
+/*
+ * EnablePrivateInt - enable a private (SGI/PPI) interrupt
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - which interrupt to enable
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void EnablePrivateInt(uint32_t gicr, uint32_t id);
+
+/*
+ * DisablePrivateInt - disable a private (SGI/PPI) interrupt
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - which interrupt to disable
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void DisablePrivateInt(uint32_t gicr, uint32_t id);
+
+/*
+ * SetPrivateIntPriority - configure the priority for a private
+ * (SGI/PPI) interrupt
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - interrupt identifier
+ *
+ * priority - 8-bit priority to program (see note below)
+ *
+ * Returns:
+ *
+ * <nothing>
+ *
+ * Note:
+ *
+ * The GICv3 architecture makes this function sensitive to the Security
+ * context in terms of what effect it has on the programmed priority: no
+ * attempt is made to adjust for the reduced priority range available
+ * when making Non-Secure accesses to the GIC
+ */
+void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority);
+
+/*
+ * GetPrivateIntPriority - configure the priority for a private
+ * (SGI/PPI) interrupt
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - interrupt identifier
+ *
+ * Returns:
+ *
+ * Int priority
+ */
+uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id);
+
+/*
+ * SetPrivateIntPending - mark a private (SGI/PPI) interrupt as pending
+ *
+ * Inputs
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void SetPrivateIntPending(uint32_t gicr, uint32_t id);
+
+/*
+ * ClearPrivateIntPending - mark a private (SGI/PPI) interrupt as not pending
+ *
+ * Inputs
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void ClearPrivateIntPending(uint32_t gicr, uint32_t id);
+
+/*
+ * GetPrivateIntPending - query whether a private (SGI/PPI) interrupt is pending
+ *
+ * Inputs
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - interrupt identifier
+ *
+ * Returns
+ *
+ * pending status
+ */
+uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id);
+
+/*
+ * SetPrivateIntSecurity - mark a private (SGI/PPI) interrupt as
+ * security <group>
+ *
+ * Inputs
+ *
+ * gicr - which Redistributor to program
+ *
+ * id - which interrupt to mark
+ *
+ * group - the group for the interrupt
+ *
+ * Returns
+ *
+ * <nothing>
+ */
+void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group);
+
+/*
+ * SetPrivateIntSecurityBlock - mark all 32 private (SGI/PPI)
+ * interrupts as security <group>
+ *
+ * Inputs:
+ *
+ * gicr - which Redistributor to program
+ *
+ * group - the group for the interrupt
+ *
+ * Returns:
+ *
+ * <nothing>
+ */
+void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group);
+
+#endif /* ndef GICV3_h */
+
+/* EOF GICv3.h */
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_aliases.h b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_aliases.h
new file mode 100644
index 00000000..826ba973
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_aliases.h
@@ -0,0 +1,113 @@
+//
+// Aliases for GICv3 registers
+//
+// Copyright (c) 2016-2017 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+#ifndef GICV3_ALIASES_H
+#define GICV3_ALIASES_H
+
+#ifndef __clang__
+
+/*
+ * Mapping of MSR and MRS to physical and virtual CPU interface registers
+ *
+ * Arm Generic Interrupt Controller Architecture Specification
+ * GIC architecture version 3.0 and version 4.0
+ * Table 8-5
+ */
+#define ICC_AP0R0_EL1 S3_0_C12_C8_4
+#define ICC_AP0R1_EL1 S3_0_C12_C8_5
+#define ICC_AP0R2_EL1 S3_0_C12_C8_6
+#define ICC_AP0R3_EL1 S3_0_C12_C8_7
+
+#define ICC_AP1R0_EL1 S3_0_C12_C9_0
+#define ICC_AP1R1_EL1 S3_0_C12_C9_1
+#define ICC_AP1R2_EL1 S3_0_C12_C9_2
+#define ICC_AP1R3_EL1 S3_0_C12_C9_3
+
+#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
+
+#define ICC_BPR0_EL1 S3_0_C12_C8_3
+#define ICC_BPR1_EL1 S3_0_C12_C12_3
+
+#define ICC_CTLR_EL1 S3_0_C12_C12_4
+#define ICC_CTLR_EL3 S3_6_C12_C12_4
+
+#define ICC_DIR_EL1 S3_0_C12_C11_1
+
+#define ICC_EOIR0_EL1 S3_0_C12_C8_1
+#define ICC_EOIR1_EL1 S3_0_C12_C12_1
+
+#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
+#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
+
+#define ICC_IAR0_EL1 S3_0_C12_C8_0
+#define ICC_IAR1_EL1 S3_0_C12_C12_0
+
+#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
+#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
+#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
+
+#define ICC_PMR_EL1 S3_0_C4_C6_0
+#define ICC_RPR_EL1 S3_0_C12_C11_3
+
+#define ICC_SGI0R_EL1 S3_0_C12_C11_7
+#define ICC_SGI1R_EL1 S3_0_C12_C11_5
+
+#define ICC_SRE_EL1 S3_0_C12_C12_5
+#define ICC_SRE_EL2 S3_4_C12_C9_5
+#define ICC_SRE_EL3 S3_6_C12_C12_5
+
+/*
+ * Mapping of MSR and MRS to virtual interface control registers
+ *
+ * Arm Generic Interrupt Controller Architecture Specification
+ * GIC architecture version 3.0 and version 4.0
+ * Table 8-6
+ */
+#define ICH_AP0R0_EL2 S3_4_C12_C8_0
+#define ICH_AP0R1_EL2 S3_4_C12_C8_1
+#define ICH_AP0R2_EL2 S3_4_C12_C8_2
+#define ICH_AP0R3_EL2 S3_4_C12_C8_3
+
+#define ICH_AP1R0_EL2 S3_4_C12_C9_0
+#define ICH_AP1R1_EL2 S3_4_C12_C9_1
+#define ICH_AP1R2_EL2 S3_4_C12_C9_2
+#define ICH_AP1R3_EL2 S3_4_C12_C9_3
+
+#define ICH_HCR_EL2 S3_4_C12_C11_0
+
+#define ICH_VTR_EL2 S3_4_C12_C11_1
+
+#define ICH_MISR_EL2 S3_4_C12_C11_2
+
+#define ICH_EISR_EL2 S3_4_C12_C11_3
+
+#define ICH_ELRSR_EL2 S3_4_C12_C11_5
+
+#define ICH_VMCR_EL2 S3_4_C12_C11_7
+
+#define ICH_LR0_EL2 S3_4_C12_C12_0
+#define ICH_LR1_EL2 S3_4_C12_C12_1
+#define ICH_LR2_EL2 S3_4_C12_C12_2
+#define ICH_LR3_EL2 S3_4_C12_C12_3
+#define ICH_LR4_EL2 S3_4_C12_C12_4
+#define ICH_LR5_EL2 S3_4_C12_C12_5
+#define ICH_LR6_EL2 S3_4_C12_C12_6
+#define ICH_LR7_EL2 S3_4_C12_C12_7
+#define ICH_LR8_EL2 S3_4_C12_C13_0
+#define ICH_LR9_EL2 S3_4_C12_C13_1
+#define ICH_LR10_EL2 S3_4_C12_C13_2
+#define ICH_LR11_EL2 S3_4_C12_C13_3
+#define ICH_LR12_EL2 S3_4_C12_C13_4
+#define ICH_LR13_EL2 S3_4_C12_C13_5
+#define ICH_LR14_EL2 S3_4_C12_C13_6
+#define ICH_LR15_EL2 S3_4_C12_C13_7
+
+#endif /* not __clang__ */
+
+#endif /* GICV3_ALIASES */
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicc.h b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicc.h
new file mode 100644
index 00000000..998d92b5
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicc.h
@@ -0,0 +1,254 @@
+/*
+ * GICv3_gicc.h - prototypes and inline functions for GICC system register operations
+ *
+ * Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+#ifndef GICV3_gicc_h
+#define GICV3_gicc_h
+
+#include "GICv3_aliases.h"
+
+#define stringify_no_expansion(x) #x
+#define stringify(x) stringify_no_expansion(x)
+
+/**********************************************************************/
+
+typedef enum
+{
+ sreSRE = (1 << 0),
+ sreDFB = (1 << 1),
+ sreDIB = (1 << 2),
+ sreEnable = (1 << 3)
+} ICC_SREBits_t;
+
+static inline void setICC_SRE_EL1(ICC_SREBits_t mode)
+{
+ asm("msr "stringify(ICC_SRE_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline uint64_t getICC_SRE_EL1(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_SRE_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline void setICC_SRE_EL2(ICC_SREBits_t mode)
+{
+ asm("msr "stringify(ICC_SRE_EL2)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline uint64_t getICC_SRE_EL2(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_SRE_EL2)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline void setICC_SRE_EL3(ICC_SREBits_t mode)
+{
+ asm("msr "stringify(ICC_SRE_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline uint64_t getICC_SRE_EL3(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_SRE_EL3)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+/**********************************************************************/
+
+typedef enum
+{
+ igrpEnable = (1 << 0),
+ igrpEnableGrp1NS = (1 << 0),
+ igrpEnableGrp1S = (1 << 2)
+} ICC_IGRPBits_t;
+
+static inline void setICC_IGRPEN0_EL1(ICC_IGRPBits_t mode)
+{
+ asm("msr "stringify(ICC_IGRPEN0_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline void setICC_IGRPEN1_EL1(ICC_IGRPBits_t mode)
+{
+ asm("msr "stringify(ICC_IGRPEN1_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline void setICC_IGRPEN1_EL3(ICC_IGRPBits_t mode)
+{
+ asm("msr "stringify(ICC_IGRPEN1_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+/**********************************************************************/
+
+typedef enum
+{
+ ctlrCBPR = (1 << 0),
+ ctlrCBPR_EL1S = (1 << 0),
+ ctlrEOImode = (1 << 1),
+ ctlrCBPR_EL1NS = (1 << 1),
+ ctlrEOImode_EL3 = (1 << 2),
+ ctlrEOImode_EL1S = (1 << 3),
+ ctlrEOImode_EL1NS = (1 << 4),
+ ctlrRM = (1 << 5),
+ ctlrPMHE = (1 << 6)
+} ICC_CTLRBits_t;
+
+static inline void setICC_CTLR_EL1(ICC_CTLRBits_t mode)
+{
+ asm("msr "stringify(ICC_CTLR_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline uint64_t getICC_CTLR_EL1(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_CTLR_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline void setICC_CTLR_EL3(ICC_CTLRBits_t mode)
+{
+ asm("msr "stringify(ICC_CTLR_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
+}
+
+static inline uint64_t getICC_CTLR_EL3(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_CTLR_EL3)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+/**********************************************************************/
+
+static inline uint64_t getICC_IAR0(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_IAR0_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline uint64_t getICC_IAR1(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_IAR1_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline void setICC_EOIR0(uint32_t interrupt)
+{
+ asm("msr "stringify(ICC_EOIR0_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
+}
+
+static inline void setICC_EOIR1(uint32_t interrupt)
+{
+ asm("msr "stringify(ICC_EOIR1_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
+}
+
+static inline void setICC_DIR(uint32_t interrupt)
+{
+ asm("msr "stringify(ICC_DIR_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
+}
+
+static inline void setICC_PMR(uint32_t priority)
+{
+ asm("msr "stringify(ICC_PMR_EL1)", %0\n; isb" :: "r" ((uint64_t)priority));
+}
+
+static inline void setICC_BPR0(uint32_t binarypoint)
+{
+ asm("msr "stringify(ICC_BPR0_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
+}
+
+static inline void setICC_BPR1(uint32_t binarypoint)
+{
+ asm("msr "stringify(ICC_BPR1_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
+}
+
+static inline uint64_t getICC_BPR0(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_BPR0_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline uint64_t getICC_BPR1(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_BPR1_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+static inline uint64_t getICC_RPR(void)
+{
+ uint64_t retc;
+
+ asm("mrs %0, "stringify(ICC_RPR_EL1)"\n" : "=r" (retc));
+
+ return retc;
+}
+
+/**********************************************************************/
+
+typedef enum
+{
+ sgirIRMTarget = 0,
+ sgirIRMAll = (1ull << 40)
+} ICC_SGIRBits_t;
+
+static inline void setICC_SGI0R(uint8_t aff3, uint8_t aff2,
+ uint8_t aff1, ICC_SGIRBits_t irm,
+ uint16_t targetlist, uint8_t intid)
+{
+ uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
+ ((uint64_t)aff1 << 16) | irm | targetlist | \
+ ((uint64_t)(intid & 0x0f) << 24));
+
+ asm("msr "stringify(ICC_SGI0R_EL1)", %0\n; isb" :: "r" (packedbits));
+}
+
+static inline void setICC_SGI1R(uint8_t aff3, uint8_t aff2,
+ uint8_t aff1, ICC_SGIRBits_t irm,
+ uint16_t targetlist, uint8_t intid)
+{
+ uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
+ ((uint64_t)aff1 << 16) | irm | targetlist | \
+ ((uint64_t)(intid & 0x0f) << 24));
+
+ asm("msr "stringify(ICC_SGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
+}
+
+static inline void setICC_ASGI1R(uint8_t aff3, uint8_t aff2,
+ uint8_t aff1, ICC_SGIRBits_t irm,
+ uint16_t targetlist, uint8_t intid)
+{
+ uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
+ ((uint64_t)aff1 << 16) | irm | targetlist | \
+ ((uint64_t)(intid & 0x0f) << 24));
+
+ asm("msr "stringify(ICC_ASGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
+}
+
+#endif /* ndef GICV3_gicc_h */
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicd.c b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicd.c
new file mode 100644
index 00000000..464ecced
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicd.c
@@ -0,0 +1,339 @@
+/*
+ * GICv3_gicd.c - generic driver code for GICv3 distributor
+ *
+ * Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+#include <stdint.h>
+
+#include "GICv3.h"
+
+typedef struct
+{
+ volatile uint32_t GICD_CTLR; // +0x0000
+ const volatile uint32_t GICD_TYPER; // +0x0004
+ const volatile uint32_t GICD_IIDR; // +0x0008
+
+ const volatile uint32_t padding0; // +0x000c
+
+ volatile uint32_t GICD_STATUSR; // +0x0010
+
+ const volatile uint32_t padding1[3]; // +0x0014
+
+ volatile uint32_t IMP_DEF[8]; // +0x0020
+
+ volatile uint32_t GICD_SETSPI_NSR; // +0x0040
+ const volatile uint32_t padding2; // +0x0044
+ volatile uint32_t GICD_CLRSPI_NSR; // +0x0048
+ const volatile uint32_t padding3; // +0x004c
+ volatile uint32_t GICD_SETSPI_SR; // +0x0050
+ const volatile uint32_t padding4; // +0x0054
+ volatile uint32_t GICD_CLRSPI_SR; // +0x0058
+
+ const volatile uint32_t padding5[3]; // +0x005c
+
+ volatile uint32_t GICD_SEIR; // +0x0068
+
+ const volatile uint32_t padding6[5]; // +0x006c
+
+ volatile uint32_t GICD_IGROUPR[32]; // +0x0080
+
+ volatile uint32_t GICD_ISENABLER[32]; // +0x0100
+ volatile uint32_t GICD_ICENABLER[32]; // +0x0180
+ volatile uint32_t GICD_ISPENDR[32]; // +0x0200
+ volatile uint32_t GICD_ICPENDR[32]; // +0x0280
+ volatile uint32_t GICD_ISACTIVER[32]; // +0x0300
+ volatile uint32_t GICD_ICACTIVER[32]; // +0x0380
+
+ volatile uint8_t GICD_IPRIORITYR[1024]; // +0x0400
+ volatile uint8_t GICD_ITARGETSR[1024]; // +0x0800
+ volatile uint32_t GICD_ICFGR[64]; // +0x0c00
+ volatile uint32_t GICD_IGRPMODR[32]; // +0x0d00
+ const volatile uint32_t padding7[32]; // +0x0d80
+ volatile uint32_t GICD_NSACR[64]; // +0x0e00
+
+ volatile uint32_t GICD_SGIR; // +0x0f00
+
+ const volatile uint32_t padding8[3]; // +0x0f04
+
+ volatile uint32_t GICD_CPENDSGIR[4]; // +0x0f10
+ volatile uint32_t GICD_SPENDSGIR[4]; // +0x0f20
+
+ const volatile uint32_t padding9[52]; // +0x0f30
+ const volatile uint32_t padding10[5120]; // +0x1000
+
+ volatile uint64_t GICD_IROUTER[1024]; // +0x6000
+} GICv3_distributor;
+
+/*
+ * use the scatter file to place GICD
+ */
+GICv3_distributor __attribute__((section(".gicd"))) gicd;
+
+void ConfigGICD(GICDCTLRFlags_t flags)
+{
+ gicd.GICD_CTLR = flags;
+}
+
+void EnableGICD(GICDCTLRFlags_t flags)
+{
+ gicd.GICD_CTLR |= flags;
+}
+
+void DisableGICD(GICDCTLRFlags_t flags)
+{
+ gicd.GICD_CTLR &= ~flags;
+}
+
+void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync)
+{
+ if (dosync)
+ {
+ const uint32_t tmask = gicdctlr_ARE_S | gicdctlr_ARE_NS;
+ const uint32_t tval = flags & tmask;
+
+ while ((gicd.GICD_CTLR & tmask) != tval)
+ continue;
+ }
+ else
+ gicd.GICD_CTLR = flags;
+}
+
+void EnableSPI(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ISENABLER has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISENABLER);
+ id &= 32 - 1;
+
+ gicd.GICD_ISENABLER[bank] = 1 << id;
+
+ return;
+}
+
+void DisableSPI(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ISENABLER has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICENABLER);
+ id &= 32 - 1;
+
+ gicd.GICD_ICENABLER[bank] = 1 << id;
+
+ return;
+}
+
+void SetSPIPriority(uint32_t id, uint32_t priority)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_IPRIORITYR has one byte-wide entry per interrupt
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
+
+ gicd.GICD_IPRIORITYR[bank] = priority;
+}
+
+uint32_t GetSPIPriority(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_IPRIORITYR has one byte-wide entry per interrupt
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
+
+ return (uint32_t)(gicd.GICD_IPRIORITYR[bank]);
+}
+
+void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_IROUTER has one doubleword-wide entry per interrupt
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
+
+ gicd.GICD_IROUTER[bank] = affinity | (uint64_t)mode;
+}
+
+uint64_t GetSPIRoute(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_IROUTER has one doubleword-wide entry per interrupt
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
+
+ return gicd.GICD_IROUTER[bank];
+}
+
+void SetSPITarget(uint32_t id, uint32_t target)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ITARGETSR has one byte-wide entry per interrupt
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
+
+ gicd.GICD_ITARGETSR[bank] = target;
+}
+
+uint32_t GetSPITarget(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ITARGETSR has one byte-wide entry per interrupt
+ */
+ /*
+ * GICD_ITARGETSR has 4 interrupts per register, i.e. 8-bits of
+ * target bitmap per register
+ */
+ bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
+
+ return (uint32_t)(gicd.GICD_ITARGETSR[bank]);
+}
+
+void ConfigureSPI(uint32_t id, GICDICFGRBits_t config)
+{
+ uint32_t bank, tmp;
+
+ /*
+ * GICD_ICFGR has 16 interrupts per register, i.e. 2-bits of
+ * configuration per register
+ */
+ bank = (id >> 4) & RANGE_LIMIT(gicd.GICD_ICFGR);
+ config &= 3;
+
+ id = (id & 0xf) << 1;
+
+ tmp = gicd.GICD_ICFGR[bank];
+ tmp &= ~(3 << id);
+ tmp |= config << id;
+ gicd.GICD_ICFGR[bank] = tmp;
+}
+
+void SetSPIPending(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ISPENDR has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISPENDR);
+ id &= 0x1f;
+
+ gicd.GICD_ISPENDR[bank] = 1 << id;
+}
+
+void ClearSPIPending(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ICPENDR has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
+ id &= 0x1f;
+
+ gicd.GICD_ICPENDR[bank] = 1 << id;
+}
+
+uint32_t GetSPIPending(uint32_t id)
+{
+ uint32_t bank;
+
+ /*
+ * GICD_ICPENDR has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
+ id &= 0x1f;
+
+ return (gicd.GICD_ICPENDR[bank] >> id) & 1;
+}
+
+void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group)
+{
+ uint32_t bank, groupmod;
+
+ /*
+ * GICD_IGROUPR has 32 interrupts per register
+ */
+ bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_IGROUPR);
+ id &= 0x1f;
+
+ /*
+ * the single group argument is split into two separate
+ * registers, so filter out and remove the (new to gicv3)
+ * group modifier bit
+ */
+ groupmod = (group >> 1) & 1;
+ group &= 1;
+
+ /*
+ * either set or clear the Group bit for the interrupt as appropriate
+ */
+ if (group)
+ gicd.GICD_IGROUPR[bank] |= 1 << id;
+ else
+ gicd.GICD_IGROUPR[bank] &= ~(1 << id);
+
+ /*
+ * now deal with groupmod
+ */
+ if (groupmod)
+ gicd.GICD_IGRPMODR[bank] |= 1 << id;
+ else
+ gicd.GICD_IGRPMODR[bank] &= ~(1 << id);
+}
+
+void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group)
+{
+ uint32_t groupmod;
+ const uint32_t nbits = (sizeof group * 8) - 1;
+
+ /*
+ * GICD_IGROUPR has 32 interrupts per register
+ */
+ block &= RANGE_LIMIT(gicd.GICD_IGROUPR);
+
+ /*
+ * get each bit of group config duplicated over all 32-bits in a word
+ */
+ groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
+ group = (uint32_t)(((int32_t)group << nbits) >> 31);
+
+ /*
+ * set the security state for this block of SPIs
+ */
+ gicd.GICD_IGROUPR[block] = group;
+ gicd.GICD_IGRPMODR[block] = groupmod;
+}
+
+void SetSPISecurityAll(GICIGROUPRBits_t group)
+{
+ uint32_t block;
+
+ /*
+ * GICD_TYPER.ITLinesNumber gives (No. SPIS / 32) - 1, and we
+ * want to iterate over all blocks excluding 0 (which are the
+ * SGI/PPI interrupts, and not relevant here)
+ */
+ for (block = (gicd.GICD_TYPER & ((1 << 5) - 1)); block > 0; --block)
+ SetSPISecurityBlock(block, group);
+}
+
+/* EOF GICv3_gicd.c */
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicr.c b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicr.c
new file mode 100644
index 00000000..26b5af8a
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/GICv3_gicr.c
@@ -0,0 +1,308 @@
+/*
+ * GICv3_gicr.c - generic driver code for GICv3 redistributor
+ *
+ * Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+#include "GICv3.h"
+
+/*
+ * physical LPI Redistributor register map
+ */
+typedef struct
+{
+ volatile uint32_t GICR_CTLR; // +0x0000 - RW - Redistributor Control Register
+ const volatile uint32_t GICR_IIDR; // +0x0004 - RO - Implementer Identification Register
+ const volatile uint32_t GICR_TYPER[2]; // +0x0008 - RO - Redistributor Type Register
+ volatile uint32_t GICR_STATUSR; // +0x0010 - RW - Error Reporting Status Register, optional
+ volatile uint32_t GICR_WAKER; // +0x0014 - RW - Redistributor Wake Register
+ const volatile uint32_t padding1[2]; // +0x0018 - RESERVED
+#ifndef USE_GIC600
+ volatile uint32_t IMPDEF1[8]; // +0x0020 - ?? - IMPLEMENTATION DEFINED
+#else
+ volatile uint32_t GICR_FCTLR; // +0x0020 - RW - Function Control Register
+ volatile uint32_t GICR_PWRR; // +0x0024 - RW - Power Management Control Register
+ volatile uint32_t GICR_CLASS; // +0x0028 - RW - Class Register
+ const volatile uint32_t padding2[5]; // +0x002C - RESERVED
+#endif
+ volatile uint64_t GICR_SETLPIR; // +0x0040 - WO - Set LPI Pending Register
+ volatile uint64_t GICR_CLRLPIR; // +0x0048 - WO - Clear LPI Pending Register
+ const volatile uint32_t padding3[8]; // +0x0050 - RESERVED
+ volatile uint64_t GICR_PROPBASER; // +0x0070 - RW - Redistributor Properties Base Address Register
+ volatile uint64_t GICR_PENDBASER; // +0x0078 - RW - Redistributor LPI Pending Table Base Address Register
+ const volatile uint32_t padding4[8]; // +0x0080 - RESERVED
+ volatile uint64_t GICR_INVLPIR; // +0x00A0 - WO - Redistributor Invalidate LPI Register
+ const volatile uint32_t padding5[2]; // +0x00A8 - RESERVED
+ volatile uint64_t GICR_INVALLR; // +0x00B0 - WO - Redistributor Invalidate All Register
+ const volatile uint32_t padding6[2]; // +0x00B8 - RESERVED
+ volatile uint64_t GICR_SYNCR; // +0x00C0 - RO - Redistributor Synchronize Register
+ const volatile uint32_t padding7[2]; // +0x00C8 - RESERVED
+ const volatile uint32_t padding8[12]; // +0x00D0 - RESERVED
+ volatile uint64_t IMPDEF2; // +0x0100 - WO - IMPLEMENTATION DEFINED
+ const volatile uint32_t padding9[2]; // +0x0108 - RESERVED
+ volatile uint64_t IMPDEF3; // +0x0110 - WO - IMPLEMENTATION DEFINED
+ const volatile uint32_t padding10[2]; // +0x0118 - RESERVED
+} GICv3_redistributor_RD;
+
+/*
+ * SGI and PPI Redistributor register map
+ */
+typedef struct
+{
+ const volatile uint32_t padding1[32]; // +0x0000 - RESERVED
+ volatile uint32_t GICR_IGROUPR0; // +0x0080 - RW - Interrupt Group Registers (Security Registers in GICv1)
+ const volatile uint32_t padding2[31]; // +0x0084 - RESERVED
+ volatile uint32_t GICR_ISENABLER; // +0x0100 - RW - Interrupt Set-Enable Registers
+ const volatile uint32_t padding3[31]; // +0x0104 - RESERVED
+ volatile uint32_t GICR_ICENABLER; // +0x0180 - RW - Interrupt Clear-Enable Registers
+ const volatile uint32_t padding4[31]; // +0x0184 - RESERVED
+ volatile uint32_t GICR_ISPENDR; // +0x0200 - RW - Interrupt Set-Pending Registers
+ const volatile uint32_t padding5[31]; // +0x0204 - RESERVED
+ volatile uint32_t GICR_ICPENDR; // +0x0280 - RW - Interrupt Clear-Pending Registers
+ const volatile uint32_t padding6[31]; // +0x0284 - RESERVED
+ volatile uint32_t GICR_ISACTIVER; // +0x0300 - RW - Interrupt Set-Active Register
+ const volatile uint32_t padding7[31]; // +0x0304 - RESERVED
+ volatile uint32_t GICR_ICACTIVER; // +0x0380 - RW - Interrupt Clear-Active Register
+ const volatile uint32_t padding8[31]; // +0x0184 - RESERVED
+ volatile uint8_t GICR_IPRIORITYR[32]; // +0x0400 - RW - Interrupt Priority Registers
+ const volatile uint32_t padding9[504]; // +0x0420 - RESERVED
+ volatile uint32_t GICR_ICnoFGR[2]; // +0x0C00 - RW - Interrupt Configuration Registers
+ const volatile uint32_t padding10[62]; // +0x0C08 - RESERVED
+ volatile uint32_t GICR_IGRPMODR0; // +0x0D00 - RW - ????
+ const volatile uint32_t padding11[63]; // +0x0D04 - RESERVED
+ volatile uint32_t GICR_NSACR; // +0x0E00 - RW - Non-Secure Access Control Register
+} GICv3_redistributor_SGI;
+
+/*
+ * We have a multiplicity of GIC Redistributors; on the GIC-AEM and
+ * GIC-500 they are arranged as one 128KB region per redistributor: one
+ * 64KB page of GICR LPI registers, and one 64KB page of GICR Private
+ * Int registers
+ */
+typedef struct
+{
+ union
+ {
+ GICv3_redistributor_RD RD_base;
+ uint8_t padding[64 * 1024];
+ } RDblock;
+
+ union
+ {
+ GICv3_redistributor_SGI SGI_base;
+ uint8_t padding[64 * 1024];
+ } SGIblock;
+} GICv3_GICR;
+
+/*
+ * use the scatter file to place GIC Redistributor base address
+ *
+ * although this code doesn't know how many Redistributor banks
+ * a particular system will have, we declare gicrbase as an array
+ * to avoid unwanted compiler optimisations when calculating the
+ * base of a particular Redistributor bank
+ */
+static const GICv3_GICR gicrbase[2] __attribute__((section (".gicr")));
+
+/**********************************************************************/
+
+/*
+ * utility functions to calculate base of a particular
+ * Redistributor bank
+ */
+
+static inline GICv3_redistributor_RD *const getgicrRD(uint32_t gicr)
+{
+ GICv3_GICR *const arraybase = (GICv3_GICR *const)&gicrbase;
+
+ return &((arraybase + gicr)->RDblock.RD_base);
+}
+
+static inline GICv3_redistributor_SGI *const getgicrSGI(uint32_t gicr)
+{
+ GICv3_GICR *arraybase = (GICv3_GICR *)(&gicrbase);
+
+ return &(arraybase[gicr].SGIblock.SGI_base);
+}
+
+/**********************************************************************/
+
+// This function walks a block of RDs to find one with the matching affinity
+uint32_t GetGICR(uint32_t affinity)
+{
+ GICv3_redistributor_RD* gicr;
+ uint32_t index = 0;
+
+ do
+ {
+ gicr = getgicrRD(index);
+ if (gicr->GICR_TYPER[1] == affinity)
+ return index;
+
+ index++;
+ }
+ while((gicr->GICR_TYPER[0] & (1<<4)) == 0); // Keep looking until GICR_TYPER.Last reports no more RDs in block
+
+ return 0xFFFFFFFF; // return -1 to signal not RD found
+}
+
+void WakeupGICR(uint32_t gicr)
+{
+ GICv3_redistributor_RD *const gicrRD = getgicrRD(gicr);
+#ifdef USE_GIC600
+ //Power up Re-distributor for GIC-600
+ gicrRD->GICR_PWRR = 0x2;
+#endif
+
+ /*
+ * step 1 - ensure GICR_WAKER.ProcessorSleep is off
+ */
+ gicrRD->GICR_WAKER &= ~gicrwaker_ProcessorSleep;
+
+ /*
+ * step 2 - wait for children asleep to be cleared
+ */
+ while ((gicrRD->GICR_WAKER & gicrwaker_ChildrenAsleep) != 0)
+ continue;
+
+ /*
+ * OK, GICR is go
+ */
+ return;
+}
+
+void EnablePrivateInt(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ id &= 0x1f;
+
+ gicrSGI->GICR_ISENABLER = 1 << id;
+}
+
+void DisablePrivateInt(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ id &= 0x1f;
+
+ gicrSGI->GICR_ICENABLER = 1 << id;
+}
+
+void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ /*
+ * GICD_IPRIORITYR has one byte-wide entry per interrupt
+ */
+ id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
+
+ gicrSGI->GICR_IPRIORITYR[id] = priority;
+}
+
+uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ /*
+ * GICD_IPRIORITYR has one byte-wide entry per interrupt
+ */
+ id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
+
+ return (uint32_t)(gicrSGI->GICR_IPRIORITYR[id]);
+}
+
+void SetPrivateIntPending(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ /*
+ * GICR_ISPENDR is one 32-bit register
+ */
+ id &= 0x1f;
+
+ gicrSGI->GICR_ISPENDR = 1 << id;
+}
+
+void ClearPrivateIntPending(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ /*
+ * GICR_ICPENDR is one 32-bit register
+ */
+ id &= 0x1f;
+
+ gicrSGI->GICR_ICPENDR = 1 << id;
+}
+
+uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+
+ /*
+ * GICR_ISPENDR is one 32-bit register
+ */
+ id &= 0x1f;
+
+ return (gicrSGI->GICR_ISPENDR >> id) & 0x01;
+}
+
+void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+ uint32_t groupmod;
+
+ /*
+ * GICR_IGROUPR0 is one 32-bit register
+ */
+ id &= 0x1f;
+
+ /*
+ * the single group argument is split into two separate
+ * registers, so filter out and remove the (new to gicv3)
+ * group modifier bit
+ */
+ groupmod = (group >> 1) & 1;
+ group &= 1;
+
+ /*
+ * either set or clear the Group bit for the interrupt as appropriate
+ */
+ if (group)
+ gicrSGI->GICR_IGROUPR0 |= 1 << id;
+ else
+ gicrSGI->GICR_IGROUPR0 &= ~(1 << id);
+
+ /*
+ * now deal with groupmod
+ */
+ if (groupmod)
+ gicrSGI->GICR_IGRPMODR0 |= 1 << id;
+ else
+ gicrSGI->GICR_IGRPMODR0 &= ~(1 << id);
+}
+
+void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group)
+{
+ GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
+ const uint32_t nbits = (sizeof group * 8) - 1;
+ uint32_t groupmod;
+
+ /*
+ * get each bit of group config duplicated over all 32-bits
+ */
+ groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
+ group = (uint32_t)(((int32_t)group << nbits) >> 31);
+
+ /*
+ * set the security state for this block of SPIs
+ */
+ gicrSGI->GICR_IGROUPR0 = group;
+ gicrSGI->GICR_IGRPMODR0 = groupmod;
+}
+
+/* EOF GICv3_gicr.c */
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.S b/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.S
new file mode 100644
index 00000000..c787c3f5
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.S
@@ -0,0 +1,133 @@
+//
+// Armv8-A AArch64 - Basic Mutex Example
+// Includes the option (USE_LSE_ATOMIC) to use Large System Extension (LSE) atomics introduced in Armv8.1-A
+//
+// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+
+ .text
+ .cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
+
+
+ .global _mutex_initialize
+ .global _mutex_acquire
+ .global _mutex_release
+
+//
+// These routines implement the mutex management functions required for running
+// the Arm C library in a multi-threaded environment.
+//
+// They use a value of 0 to represent an unlocked mutex, and 1 for a locked mutex
+//
+// **********************************************************************
+//
+
+ .type _mutex_initialize, "function"
+ .cfi_startproc
+_mutex_initialize:
+
+ //
+ // mark the mutex as unlocked
+ //
+ mov w1, #0
+ str w1, [x0]
+
+ //
+ // we are running multi-threaded, so set a non-zero return
+ // value (function prototype says use 1)
+ //
+ mov w0, #1
+ ret
+ .cfi_endproc
+
+#if !defined(USE_LSE_ATOMIC)
+
+ .type _mutex_acquire, "function"
+ .cfi_startproc
+_mutex_acquire:
+
+ //
+ // send ourselves an event, so we don't stick on the wfe at the
+ // top of the loop
+ //
+ sevl
+
+ //
+ // wait until the mutex is available
+ //
+loop:
+ wfe
+ ldaxr w1, [x0]
+ cbnz w1, loop
+
+ //
+ // mutex is (at least, it was) available - try to claim it
+ //
+ mov w1, #1
+ stxr w2, w1, [x0]
+ cbnz w2, loop
+
+ //
+ // OK, we have the mutex, our work is done here
+ //
+ ret
+ .cfi_endproc
+
+
+ .type _mutex_release, "function"
+ .cfi_startproc
+_mutex_release:
+
+ mov w1, #0
+ stlr w1, [x0]
+ ret
+ .cfi_endproc
+
+#else // LSE version
+
+ .type _mutex_acquire, "function"
+ .cfi_startproc
+_mutex_acquire:
+ // This uses a "ticket lock". The lock is stored as a 32-bit value:
+ // - the upper 16-bits record the thread's ticket number ("take a ticket")
+ // - the lower 16-bits record the ticket being served ("now serving")
+
+ // atomically load then increment the thread's ticket number ("take a ticket")
+ mov w3, #(1 << 16)
+ ldadda w3, w1, [x0]
+
+ // is the ticket now being served?
+ eor w2, w1, w1, ror #16
+ cbz w2, loop_exit
+
+ // no, so wait for the ticket to be served
+
+ // send a local event to avoid missing an unlock before the exclusive load
+ sevl
+
+loop:
+ wfe
+ ldaxrh w3, [x0]
+ eor w2, w3, w1, lsr #16
+ cbnz w2, loop
+
+ //
+ // OK, we have the mutex, our work is done here
+ //
+loop_exit:
+ ret
+ .cfi_endproc
+
+
+ .type _mutex_release, "function"
+ .cfi_startproc
+_mutex_release:
+ mov w1, #1
+ staddlh w1, [x0]
+ ret
+ .cfi_endproc
+#endif
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.h b/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.h
new file mode 100644
index 00000000..ec1a1d28
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/MP_Mutexes.h
@@ -0,0 +1,66 @@
+/*
+ * Armv8-A AArch64 - Basic Mutex Example
+ *
+ * Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+#ifndef MP_MUTEX_H
+#define MP_MUTEX_H
+
+/*
+ * The Arm C library calls-out to these functions to manage multithreading.
+ * They can also be called by user application code.
+ *
+ * Mutex type is specified by the Arm C library
+ *
+ * Declare function prototypes for libc mutex routines
+ */
+typedef signed int *mutex;
+
+/*
+ * int _mutex_initialize(mutex *m)
+ *
+ * Inputs
+ * mutex *m - pointer to the 32-bit word associated with the mutex
+ *
+ * Returns
+ * 0 - application is non-threaded
+ * 1 - application is threaded
+ * The C library uses the return result to indicate whether it is being used in a multithreaded environment.
+ */
+int _mutex_initialize(mutex *m);
+
+/*
+ * void _mutex_acquire(mutex *m)
+ *
+ * Inputs
+ * mutex *m - pointer to the 32-bit word associated with the mutex
+ *
+ * Returns
+ * <nothing>
+ *
+ * Side Effects
+ * Routine does not return until the mutex has been claimed. A load-acquire
+ * is used to guarantee that the mutex claim is properly ordered with
+ * respect to any accesses to the resource protected by the mutex
+ */
+void _mutex_acquire(mutex *m);
+
+/*
+ * void _mutex_release(mutex *m)
+ *
+ * Inputs
+ * mutex *m - pointer to the 32-bit word associated with the mutex
+ *
+ * Returns
+ * <nothing>
+ *
+ * Side Effects
+ * A store-release is used to guarantee that the mutex release is properly
+ * ordered with respect any accesses to the resource protected by the mutex
+ */
+void _mutex_release(mutex *m);
+
+#endif
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/PPM_AEM.h b/ports/cortex_a72/gnu/example_build/sample_threadx/PPM_AEM.h
new file mode 100644
index 00000000..f7501eeb
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/PPM_AEM.h
@@ -0,0 +1,66 @@
+//
+// Private Peripheral Map for the v8 Architecture Envelope Model
+//
+// Copyright (c) 2012-2017 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+#ifndef PPM_AEM_H
+#define PPM_AEM_H
+
+//
+// Distributor layout
+//
+#define GICD_CTLR 0x0000
+#define GICD_TYPER 0x0004
+#define GICD_IIDR 0x0008
+#define GICD_IGROUP 0x0080
+#define GICD_ISENABLE 0x0100
+#define GICD_ICENABLE 0x0180
+#define GICD_ISPEND 0x0200
+#define GICD_ICPEND 0x0280
+#define GICD_ISACTIVE 0x0300
+#define GICD_ICACTIVE 0x0380
+#define GICD_IPRIORITY 0x0400
+#define GICD_ITARGETS 0x0800
+#define GICD_ICFG 0x0c00
+#define GICD_PPISR 0x0d00
+#define GICD_SPISR 0x0d04
+#define GICD_SGIR 0x0f00
+#define GICD_CPENDSGI 0x0f10
+#define GICD_SPENDSGI 0x0f20
+#define GICD_PIDR4 0x0fd0
+#define GICD_PIDR5 0x0fd4
+#define GICD_PIDR6 0x0fd8
+#define GICD_PIDR7 0x0fdc
+#define GICD_PIDR0 0x0fe0
+#define GICD_PIDR1 0x0fe4
+#define GICD_PIDR2 0x0fe8
+#define GICD_PIDR3 0x0fec
+#define GICD_CIDR0 0x0ff0
+#define GICD_CIDR1 0x0ff4
+#define GICD_CIDR2 0x0ff8
+#define GICD_CIDR3 0x0ffc
+
+//
+// CPU Interface layout
+//
+#define GICC_CTLR 0x0000
+#define GICC_PMR 0x0004
+#define GICC_BPR 0x0008
+#define GICC_IAR 0x000c
+#define GICC_EOIR 0x0010
+#define GICC_RPR 0x0014
+#define GICC_HPPIR 0x0018
+#define GICC_ABPR 0x001c
+#define GICC_AIAR 0x0020
+#define GICC_AEOIR 0x0024
+#define GICC_AHPPIR 0x0028
+#define GICC_APR0 0x00d0
+#define GICC_NSAPR0 0x00e0
+#define GICC_IIDR 0x00fc
+#define GICC_DIR 0x1000
+
+#endif // PPM_AEM_H
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c
new file mode 100644
index 00000000..17cceb01
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.c
@@ -0,0 +1,393 @@
+/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
+ threads of different priorities, using a message queue, semaphore, mutex, event flags group,
+ byte pool, and block pool. */
+
+#include "tx_api.h"
+
+
+extern void init_timer(void); /* in timer_interrupts.c */
+
+
+#define DEMO_STACK_SIZE 1024
+#define DEMO_BYTE_POOL_SIZE 9120
+#define DEMO_BLOCK_POOL_SIZE 100
+#define DEMO_QUEUE_SIZE 100
+
+
+/* Define byte pool memory. */
+
+UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
+
+
+
+
+/* Define the ThreadX object control blocks... */
+
+TX_THREAD thread_0;
+TX_THREAD thread_1;
+TX_THREAD thread_2;
+TX_THREAD thread_3;
+TX_THREAD thread_4;
+TX_THREAD thread_5;
+TX_THREAD thread_6;
+TX_THREAD thread_7;
+TX_TIMER timer_0;
+TX_QUEUE queue_0;
+TX_SEMAPHORE semaphore_0;
+TX_MUTEX mutex_0;
+TX_EVENT_FLAGS_GROUP event_flags_0;
+TX_BYTE_POOL byte_pool_0;
+TX_BLOCK_POOL block_pool_0;
+
+
+/* Define the counters used in the demo application... */
+
+ULONG thread_0_counter;
+ULONG thread_1_counter;
+ULONG thread_1_messages_sent;
+ULONG thread_2_counter;
+ULONG thread_2_messages_received;
+ULONG thread_3_counter;
+ULONG thread_4_counter;
+ULONG thread_5_counter;
+ULONG thread_6_counter;
+ULONG thread_7_counter;
+
+
+/* Define thread prototypes. */
+
+void thread_0_entry(ULONG thread_input);
+void thread_1_entry(ULONG thread_input);
+void thread_2_entry(ULONG thread_input);
+void thread_3_and_4_entry(ULONG thread_input);
+void thread_5_entry(ULONG thread_input);
+void thread_6_and_7_entry(ULONG thread_input);
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+UCHAR event_buffer[65536];
+
+#endif
+
+
+/* Define main entry point. */
+
+int main(void)
+{
+
+ /* Initialize timer. */
+ init_timer();
+
+ /* Enter ThreadX. */
+ tx_kernel_enter();
+
+ return 0;
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+CHAR *pointer = TX_NULL;
+
+
+#ifdef TX_ENABLE_EVENT_TRACE
+
+ tx_trace_enable(event_buffer, sizeof(event_buffer), 32);
+#endif
+
+ /* Create a byte memory pool from which to allocate the thread stacks. */
+ tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, DEMO_BYTE_POOL_SIZE);
+
+ /* Allocate the stack for thread 0. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create the main thread. */
+ tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
+ pointer, DEMO_STACK_SIZE,
+ 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 1. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 1 and 2. These threads pass information through a ThreadX
+ message queue. It is also interesting to note that these threads have a time
+ slice. */
+ tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 2. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
+ pointer, DEMO_STACK_SIZE,
+ 16, 16, 4, TX_AUTO_START);
+
+ /* Allocate the stack for thread 3. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
+ An interesting thing here is that both threads share the same instruction area. */
+ tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 4. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 5. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create thread 5. This thread simply pends on an event flag which will be set
+ by thread_0. */
+ tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
+ pointer, DEMO_STACK_SIZE,
+ 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 6. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
+ tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the stack for thread 7. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
+
+ tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
+ pointer, DEMO_STACK_SIZE,
+ 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
+
+ /* Allocate the message queue. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
+
+ /* Create the message queue shared by threads 1 and 2. */
+ tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
+
+ /* Create the semaphore used by threads 3 and 4. */
+ tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
+
+ /* Create the event flags group used by threads 1 and 5. */
+ tx_event_flags_create(&event_flags_0, "event flags 0");
+
+ /* Create the mutex used by thread 6 and 7 without priority inheritance. */
+ tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
+
+ /* Allocate the memory for a small block pool. */
+ tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
+
+ /* Create a block memory pool to allocate a message buffer from. */
+ tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
+
+ /* Allocate a block and release the block memory. */
+ tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
+
+ /* Release the block back to the pool. */
+ tx_block_release(pointer);
+}
+
+
+/* Define the test threads. */
+
+void thread_0_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sits in while-forever-sleep loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_0_counter++;
+
+ /* Sleep for 10 ticks. */
+ tx_thread_sleep(10);
+
+ /* Set event flag 0 to wakeup thread 5. */
+ status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
+
+
+void thread_1_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This thread simply sends messages to a queue shared by thread 2. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_1_counter++;
+
+ /* Send message to queue 0. */
+ status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
+
+ /* Check completion status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Increment the message sent. */
+ thread_1_messages_sent++;
+ }
+}
+
+
+void thread_2_entry(ULONG thread_input)
+{
+
+ULONG received_message;
+UINT status;
+
+ /* This thread retrieves messages placed on the queue by thread 1. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_2_counter++;
+
+ /* Retrieve a message from the queue. */
+ status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
+
+ /* Check completion status and make sure the message is what we
+ expected. */
+ if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
+ break;
+
+ /* Otherwise, all is okay. Increment the received message count. */
+ thread_2_messages_received++;
+ }
+}
+
+
+void thread_3_and_4_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 3 and thread 4. As the loop
+ below shows, these function compete for ownership of semaphore_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 3)
+ thread_3_counter++;
+ else
+ thread_4_counter++;
+
+ /* Get the semaphore with suspension. */
+ status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the semaphore. */
+ tx_thread_sleep(2);
+
+ /* Release the semaphore. */
+ status = tx_semaphore_put(&semaphore_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
+
+
+void thread_5_entry(ULONG thread_input)
+{
+
+UINT status;
+ULONG actual_flags;
+
+
+ /* This thread simply waits for an event in a forever loop. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ thread_5_counter++;
+
+ /* Wait for event flag 0. */
+ status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
+ &actual_flags, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if ((status != TX_SUCCESS) || (actual_flags != 0x1))
+ break;
+ }
+}
+
+
+void thread_6_and_7_entry(ULONG thread_input)
+{
+
+UINT status;
+
+
+ /* This function is executed from thread 6 and thread 7. As the loop
+ below shows, these function compete for ownership of mutex_0. */
+ while(1)
+ {
+
+ /* Increment the thread counter. */
+ if (thread_input == 6)
+ thread_6_counter++;
+ else
+ thread_7_counter++;
+
+ /* Get the mutex with suspension. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Get the mutex again with suspension. This shows
+ that an owning thread may retrieve the mutex it
+ owns multiple times. */
+ status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Sleep for 2 ticks to hold the mutex. */
+ tx_thread_sleep(2);
+
+ /* Release the mutex. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+
+ /* Release the mutex again. This will actually
+ release ownership since it was obtained twice. */
+ status = tx_mutex_put(&mutex_0);
+
+ /* Check status. */
+ if (status != TX_SUCCESS)
+ break;
+ }
+}
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.launch b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.launch
new file mode 100644
index 00000000..2b75e0ee
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.launch
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="com.arm.debugger.launcher2">
+ <stringAttribute key="ANDROID_ACTIVITY_NAME" value=""/>
+ <stringAttribute key="ANDROID_APPLICATION" value=""/>
+ <stringAttribute key="ANDROID_APP_DIR" value=""/>
+ <stringAttribute key="ANDROID_PROCESS_NAME" value=""/>
+ <mapAttribute key="AverageDurationTracker">
+ <mapEntry key="*Fetching Data Model" value="210253"/>
+ <mapEntry key="*list global low level symbols" value="1091370"/>
+ <mapEntry key="*loading memory from target" value="820184"/>
+ <mapEntry key="*loading values from target" value="7611554"/>
+ <mapEntry key="*trace" value="322915988"/>
+ <mapEntry key="*updating expressions" value="82423423"/>
+ <mapEntry key="*updating registers" value="71328946"/>
+ <mapEntry key="*updating variables" value="8591428"/>
+ <mapEntry key="Add Watchpoint" value="24597988"/>
+ <mapEntry key="AddEventObserver" value="2339600"/>
+ <mapEntry key="Evaluate" value="1178890"/>
+ <mapEntry key="GlobalsLoaderCommand" value="154351059"/>
+ <mapEntry key="areCachesAvailable" value="512640"/>
+ <mapEntry key="backtrace" value="5112231"/>
+ <mapEntry key="break" value="4014913"/>
+ <mapEntry key="checking tracepoints" value="200317"/>
+ <mapEntry key="compute execution mode" value="466572"/>
+ <mapEntry key="continue" value="15148060"/>
+ <mapEntry key="core" value="3940900"/>
+ <mapEntry key="directory" value="1503592"/>
+ <mapEntry key="disable" value="1478680"/>
+ <mapEntry key="disassemble" value="57572371"/>
+ <mapEntry key="enable" value="1860234"/>
+ <mapEntry key="evaluate" value="2783965"/>
+ <mapEntry key="evaluate address" value="17239727"/>
+ <mapEntry key="get byte order" value="472733"/>
+ <mapEntry key="get capabilities" value="202552"/>
+ <mapEntry key="get execution addresss" value="394564"/>
+ <mapEntry key="get source lines" value="295618"/>
+ <mapEntry key="get substitute paths" value="353179"/>
+ <mapEntry key="get value" value="402104"/>
+ <mapEntry key="getValidEncodings" value="513752"/>
+ <mapEntry key="initialize command help" value="74015139"/>
+ <mapEntry key="interrupt" value="7175224"/>
+ <mapEntry key="list breakpoint options" value="199731"/>
+ <mapEntry key="list breakpoints" value="630899"/>
+ <mapEntry key="list instruction sets" value="261430"/>
+ <mapEntry key="list signals" value="407465"/>
+ <mapEntry key="list source files" value="864344"/>
+ <mapEntry key="list watchpoint options" value="268722"/>
+ <mapEntry key="list watchpoints" value="488478"/>
+ <mapEntry key="loadfile" value="37843801"/>
+ <mapEntry key="next" value="28879002"/>
+ <mapEntry key="nexti" value="29780513"/>
+ <mapEntry key="remove" value="1542853"/>
+ <mapEntry key="run script" value="33363950"/>
+ <mapEntry key="set CWD" value="2457367"/>
+ <mapEntry key="set breakpoint properties" value="5020796"/>
+ <mapEntry key="set debug-from" value="865786"/>
+ <mapEntry key="set substitute-path" value="8017078"/>
+ <mapEntry key="set watchpoint properties" value="1458988"/>
+ <mapEntry key="source use_model_semihosting.ds" value="3779014"/>
+ <mapEntry key="start" value="14956585"/>
+ <mapEntry key="step" value="30965896"/>
+ <mapEntry key="stepi" value="30815174"/>
+ <mapEntry key="synchronizing trace ranges" value="26037"/>
+ <mapEntry key="toggleBreakpoint" value="7270567"/>
+ <mapEntry key="waitForTargetToStop" value="10448502"/>
+ <mapEntry key="write expression" value="5812240"/>
+ </mapAttribute>
+ <listAttribute key="DEBUG_TAB."/>
+ <stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/>
+ <stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/tx}"/>
+ <intAttribute key="DEBUG_TAB..RESOURCES.COUNT" value="1"/>
+ <intAttribute key="FILES.CONNECT_TO_GDB_SERVER.RESOURCES.COUNT" value="0"/>
+ <intAttribute key="FILES.DEBUG_EXISTING_ANDROID.RESOURCES.COUNT" value="0"/>
+ <listAttribute key="FILES.DEBUG_RESIDENT_ANDROID"/>
+ <stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
+ <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.VALUE" value=""/>
+ <stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="APPLICATION_ON_TARGET"/>
+ <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">
+ <listEntry value="ON_DEMAND_LOAD"/>
+ <listEntry value="ALSO_LOAD_SYMBOLS"/>
+ </listAttribute>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <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.VALUE" value=""/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.TYPE" value="TARGET_DOWNLOAD_DIR"/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
+ <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">
+ <listEntry value="ON_DEMAND_LOAD"/>
+ <listEntry value="ALSO_LOAD_SYMBOLS"/>
+ </listAttribute>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <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.VALUE" value=""/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.TYPE" value="TARGET_DOWNLOAD_DIR"/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
+ <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"/>
+ <listAttribute key="FILES.ICE_DEBUG">
+ <listEntry value="ON_DEMAND_LOAD"/>
+ <listEntry value="ALSO_LOAD_SYMBOLS"/>
+ </listAttribute>
+ <stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
+ <stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}"/>
+ <intAttribute key="FILES.ICE_DEBUG.RESOURCES.COUNT" value="1"/>
+ <listAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE">
+ <listEntry value="ON_DEMAND_LOAD"/>
+ <listEntry value="ALSO_LOAD_SYMBOLS"/>
+ </listAttribute>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.VALUE" value=""/>
+ <intAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.COUNT" value="1"/>
+ <listAttribute key="FILES.ICE_DEBUG_WITH_TRACE">
+ <listEntry value="ON_DEMAND_LOAD"/>
+ <listEntry value="ALSO_LOAD_SYMBOLS"/>
+ </listAttribute>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
+ <stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.VALUE" value=""/>
+ <intAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.COUNT" value="1"/>
+ <stringAttribute key="FILES.SELECTED_DEBUG_OPEATION" value="ICE_DEBUG"/>
+ <stringAttribute key="HOST_WORKING_DIR" value="${workspace_loc}"/>
+ <booleanAttribute key="HOST_WORKING_DIR_USE_DEFAULT" value="true"/>
+ <booleanAttribute key="InstructionStepping" value="false"/>
+ <booleanAttribute key="KEY_COMMANDS_AFTER_CONNECT" value="true"/>
+ <stringAttribute key="KEY_COMMANDS_AFTER_CONNECT_TEXT" value="add-symbol-file &quot;${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}&quot; EL1N:0"/>
+ <booleanAttribute key="KEY_COMMANDS_AS_CONNECT" value="false"/>
+ <intAttribute key="Messages.POST_TRIGGER_CAPTURE_SIZE.getLocalisedValue().FMTrace" value="50"/>
+ <booleanAttribute key="Messages.STOP_ON_TRIGGER.getLocalisedValue().FMTrace" value="false"/>
+ <booleanAttribute key="RSE_USE_HOSTNAME" 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">
+ <listEntry value="NODE CACHE VERSION 1"/>
+ <listEntry value="EXPRESSION_GROUP:Expressions:VALUE:gic_dist:VALUE:(gic_dist)-&gt;padding0"/>
+ <listEntry value="1"/>
+ <listEntry value="element formatter"/>
+ <listEntry value="Unsigned Decimal"/>
+ <listEntry value="EXPRESSION_GROUP:Expressions:VALUE:_tx_thread_current_ptr-&gt;tx_thread_name"/>
+ <listEntry value="1"/>
+ <listEntry value="element formatter"/>
+ <listEntry value="Character"/>
+ <listEntry value="EXPRESSION_GROUP:Expressions:VALUE:$AARCH64::$Core::$SP"/>
+ <listEntry value="1"/>
+ <listEntry value="formatter"/>
+ <listEntry value="Hexadecimal"/>
+ </listAttribute>
+ <listAttribute key="TREE_NODE_PROPERTIES:debugger.view.NewRegisterView">
+ <listEntry value="NODE CACHE VERSION 1"/>
+ <listEntry value="REGISTER_SET:$AARCH64"/>
+ <listEntry value="1"/>
+ <listEntry value="expanded"/>
+ <listEntry value="true"/>
+ <listEntry value="REGISTER_GROUP:$AARCH64::$Core"/>
+ <listEntry value="1"/>
+ <listEntry value="expanded"/>
+ <listEntry value="true"/>
+ </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="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;breakpoints order=&quot;ALPHA&quot;&gt;&#10;&#9;&lt;breakpoint ignorecount=&quot;0&quot; threadenabled=&quot;no&quot; core_list=&quot;&quot; continue=&quot;no&quot; verboseBreakpoints=&quot;yes&quot; kind=&quot;SOURCEPOSITION&quot;&gt;&#10;&#9;&#9;&lt;master_location index=&quot;0&quot; enabled=&quot;true&quot; version=&quot;2&quot; address=&quot;EL3:0x0000000080000800&quot; debugFile=&quot;C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S&quot; hostFile=&quot;C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S&quot; line=&quot;27&quot;/&gt;&#10;&#9;&#9;&lt;location index=&quot;0&quot; enabled=&quot;true&quot; version=&quot;2&quot; address=&quot;EL3:0x0000000080000800&quot; debugFile=&quot;C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S&quot; hostFile=&quot;C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S&quot; line=&quot;27&quot;/&gt;&#10;&#9;&#9;&lt;location index=&quot;1&quot; enabled=&quot;true&quot; version=&quot;2&quot; address=&quot;EL1N:0x0000000080000800&quot; debugFile=&quot;C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S&quot; hostFile=&quot;C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S&quot; line=&quot;27&quot;/&gt;&#10;&#9;&lt;/breakpoint&gt;&#10;&lt;/breakpoints&gt;&#10;"/>
+ <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
+ <listEntry value="&lt;Next Instruction&gt;"/>
+ <listEntry value=""/>
+ <listEntry value="EL1N:0x0000000080006444"/>
+ <listEntry value="EL1N:0x000000008000A7E4"/>
+ <listEntry value="0x0000000080009140"/>
+ <listEntry value="0x000000008000E660"/>
+ <listEntry value="EL1N:0x000000008000E660"/>
+ </listAttribute>
+ <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
+ <listEntry value="100"/>
+ <listEntry value=""/>
+ <listEntry value="100"/>
+ <listEntry value="100"/>
+ <listEntry value="100"/>
+ <listEntry value="100"/>
+ <listEntry value="100"/>
+ </listAttribute>
+ <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.addresses">
+ <listEntry value=""/>
+ <listEntry value="0x000000008000E600"/>
+ <listEntry value="0x000000008000EE00"/>
+ <listEntry value="thread_2.tx_thread_stack_start"/>
+ <listEntry value="0x000000008000E500"/>
+ <listEntry value="0x000000008000E670"/>
+ <listEntry value="0x8000de30"/>
+ <listEntry value="0x8000de00"/>
+ <listEntry value="0x8000de48"/>
+ </listAttribute>
+ <listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.ranges">
+ <listEntry value=""/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ <listEntry value="1024"/>
+ </listAttribute>
+ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
+ <listEntry value="_tx_thread_schedule"/>
+ <listEntry value="&lt;Next Instruction&gt;"/>
+ </listAttribute>
+ <listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
+ <listEntry value="100"/>
+ <listEntry value="100"/>
+ </listAttribute>
+ <stringAttribute key="config_db_activity_name" value="Debug Cortex-A72"/>
+ <stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option dtsl_config_script model_params config_file 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 (Installed with Arm DS) - Base_A72x1"/>
+ <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_installedwitharmds_/base_a35x1"/>
+ <stringAttribute key="config_file" value="CDB://cadi_config.xml"/>
+ <booleanAttribute key="connectOnly" value="false"/>
+ <listAttribute key="debugger.view.DisassemblyView:current">
+ <listEntry value="&lt;Next Instruction&gt;"/>
+ <listEntry value="100"/>
+ </listAttribute>
+ <listAttribute key="debugger.view.DisassemblyView:current:133102083840333696.viewid=2">
+ <listEntry value="&lt;Next Instruction&gt;"/>
+ <listEntry value="100"/>
+ </listAttribute>
+ <listAttribute key="debugger.view.DisassemblyView:current:3239034212381883008.viewid=2">
+ <listEntry value="_tx_thread_schedule"/>
+ <listEntry value="100"/>
+ </listAttribute>
+ <listAttribute key="debugger.view.DisassemblyView:current:4564877728016551851.viewid=3">
+ <listEntry value=""/>
+ <listEntry value=""/>
+ </listAttribute>
+ <listAttribute key="debugger.view.ExpressionsView">
+ <listEntry value="thread_0_counter"/>
+ <listEntry value="thread_1_counter"/>
+ <listEntry value="thread_2_counter"/>
+ <listEntry value="thread_3_counter"/>
+ <listEntry value="thread_4_counter"/>
+ <listEntry value="thread_5_counter"/>
+ <listEntry value="thread_6_counter"/>
+ <listEntry value="thread_7_counter"/>
+ </listAttribute>
+ <listAttribute key="debugger.view.ExpressionsView.ExpressionTypes">
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ <listEntry value=""/>
+ </listAttribute>
+ <mapAttribute key="debugger.view.ExpressionsView.ExpressionsData">
+ <mapEntry key="0" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <mapEntry key="1" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <mapEntry key="2" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <mapEntry key="3" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <mapEntry key="4" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <mapEntry key="5" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
+ <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&#9;8&#9;0&#9;true&#9;true&#9;187&#9;-1&#9;true&#9;1&#9;false&#9;true&#9;90&#9;-1&#9;true&#9;2&#9;true&#9;true&#9;108&#9;-1&#9;true&#9;3&#9;true&#9;true&#9;57&#9;-1&#9;true&#9;4&#9;true&#9;true&#9;50&#9;-1&#9;true&#9;5&#9;true&#9;true&#9;37&#9;-1&#9;true&#9;6&#9;true&#9;true&#9;157&#9;-1&#9;true&#9;7&#9;true&#9;true&#9;53&#9;-1&#9;true"/>
+ <stringAttribute key="debugger.view.MemoryView" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;page&gt;&#10;&#9;&lt;memoryView/&gt;&#10;&lt;/page&gt;&#10;"/>
+ <listAttribute key="debugger.view.MemoryView:current">
+ <listEntry value=""/>
+ <listEntry value=""/>
+ </listAttribute>
+ <stringAttribute key="debugger.view.NewRegisterView:DebugOutlineColumnState" value="OutlineConfig1&#9;8&#9;0&#9;true&#9;false&#9;206&#9;-1&#9;true&#9;1&#9;false&#9;true&#9;90&#9;-1&#9;true&#9;2&#9;true&#9;false&#9;420&#9;-1&#9;true&#9;3&#9;false&#9;true&#9;41&#9;-1&#9;true&#9;4&#9;false&#9;true&#9;50&#9;-1&#9;true&#9;5&#9;true&#9;false&#9;37&#9;-1&#9;true&#9;6&#9;false&#9;true&#9;62&#9;-1&#9;true&#9;7&#9;true&#9;false&#9;53&#9;-1&#9;true"/>
+ <stringAttribute key="debugger.view.NewRegisterView:_selectedRegisterSet" value="All registers"/>
+ <mapAttribute key="debugger.view.NewRegisterView_registerSets"/>
+ <stringAttribute key="debugger.view.StackView:DebugOutlineColumnState" value="OutlineConfig1&#9;8&#9;0&#9;true&#9;true&#9;49&#9;-1&#9;true&#9;1&#9;false&#9;true&#9;90&#9;-1&#9;true&#9;2&#9;true&#9;true&#9;45&#9;-1&#9;true&#9;3&#9;true&#9;true&#9;41&#9;-1&#9;true&#9;4&#9;true&#9;true&#9;50&#9;-1&#9;true&#9;5&#9;true&#9;true&#9;37&#9;-1&#9;true&#9;6&#9;true&#9;true&#9;62&#9;-1&#9;true&#9;7&#9;true&#9;true&#9;53&#9;-1&#9;true"/>
+ <listAttribute key="debugger.view.TraceView:TRACE_EXPORT_FILTERS"/>
+ <stringAttribute key="debugger.view.VariableTreeView:DebugOutlineColumnState" value="OutlineConfig1&#9;0"/>
+ <listAttribute key="debugger.view.VariableTreeView:USER_ADDED_FILE_STATICS"/>
+ <listAttribute key="debugger.view.VariableTreeView:USER_ADDED_GLOBALS"/>
+ <listAttribute key="debugger.view.VariableTreeView:USER_ADDED_UNRESOLVED"/>
+ <booleanAttribute key="debugger.view.expression.DrawAsHex" value="false"/>
+ <booleanAttribute key="debugger.view.register.DrawAsHex" value="false"/>
+ <stringAttribute key="dtsl_config" value="DtslScript"/>
+ <stringAttribute key="dtsl_config_script" value="CDB://dtsl_config_script.py"/>
+ <stringAttribute key="dtsl_options_file" value="default"/>
+ <stringAttribute key="dtsl_tracecapture_option" value="options.traceBuffer.traceCaptureDevice"/>
+ <stringAttribute key="launch_configuration_version" value="5.21.1"/>
+ <booleanAttribute key="linuxOS" value="false"/>
+ <stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/>
+ <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="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
+ <mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
+ </mapAttribute>
+ <listAttribute key="setup">
+ <listEntry value="CDB://Scripts/rtsm_launcher.py"/>
+ <listEntry value="&quot;FVP_Base_Cortex-A72x1&quot;"/>
+ </listAttribute>
+ <stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/>
+ <stringAttribute key="substitutePath" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;tuplelist&gt;&#10;&#9;&lt;tuple&gt;&#10;&#9;&#9;&lt;ta&gt;C:\temp1702\tx\&lt;/ta&gt;&#10;&#9;&#9;&lt;tb&gt;C:\temp1702\tx\&lt;/tb&gt;&#10;&#9;&lt;/tuple&gt;&#10;&lt;/tuplelist&gt;&#10;"/>
+ <stringAttribute key="watchpoints" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;watchpoints&gt;&#10;&lt;/watchpoints&gt;&#10;"/>
+</launchConfiguration>
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.ld b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.ld
new file mode 100644
index 00000000..eec8f12b
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sample_threadx.ld
@@ -0,0 +1,245 @@
+/* Linker script to place sections and symbol values.
+ * It references following symbols, which must be defined in code:
+ * start64 : Entry point
+ *
+ * It defines following symbols, which code can use without definition:
+ * __cs3_peripherals
+ * __code_start
+ * __exidx_start
+ * __exidx_end
+ * __data_start
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * __stack
+ * __el3_stack
+ * __ttb0_l1
+ * __ttb0_l2_ram
+ * __ttb0_l2_private
+ * __ttb0_l2_periph
+ * __top_of_ram
+ */
+
+ENTRY(start64)
+
+SECTIONS
+{
+ /*
+ * CS3 Peripherals is a 64MB region from 0x1c000000
+ * that includes the following:
+ * System Registers at 0x1C010000
+ * UART0 (PL011) at 0x1C090000
+ * Color LCD Controller (PL111) at 0x1C1F0000
+ * plus a number of others.
+ * CS3_PERIPHERALS is used by the startup code for page-table generation
+ * This region is not truly empty, but we have no
+ * predefined objects that live within it
+ */
+ __cs3_peripherals = 0x1c000000;
+
+ /*
+ * GICv3 distributor
+ */
+ .gicd 0x2f000000 (NOLOAD):
+ {
+ *(.gicd)
+ }
+
+ /*
+ * GICv3 redistributors
+ * 128KB for each redistributor in the system
+ */
+ .gicr 0x2f100000 (NOLOAD):
+ {
+ *(.gicr)
+ }
+
+ .vectors 0x80000000:
+ {
+ __code_start = .;
+ KEEP(*(StartUp))
+ KEEP(*(EL1VECTORS EL2VECTORS EL3VECTORS))
+ }
+
+ .init :
+ {
+ KEEP (*(SORT_NONE(.init)))
+ }
+
+ .text :
+ {
+ *(.text*)
+ }
+
+ .fini :
+ {
+ KEEP (*(SORT_NONE(.fini)))
+ }
+
+ .rodata :
+ {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ }
+
+ .eh_frame :
+ {
+ KEEP (*(.eh_frame))
+ }
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ }
+
+ .ARM.exidx :
+ {
+ __exidx_start = .;
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ __exidx_end = .;
+ }
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array ))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT(.fini_array.*)))
+ KEEP (*(.fini_array ))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+
+ .jcr :
+ {
+ KEEP (*(.jcr))
+ }
+
+ .data :
+ {
+ __data_start = . ;
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ }
+
+ .heap (NOLOAD):
+ {
+ . = ALIGN(64);
+ __end__ = .;
+ PROVIDE(end = .);
+ . = . + 0x1000;
+ }
+
+ .stack (NOLOAD):
+ {
+ . = ALIGN(64);
+ . = . + 8 * 0x4000;
+ __handler_stack = .;
+ }
+
+ .stack (NOLOAD):
+ {
+ . = ALIGN(64);
+ . = . + 8 * 0x4000;
+ __stack = .;
+ }
+
+ .el3_stack (NOLOAD):
+ {
+ . = ALIGN(64);
+ . = . + 8 * 0x1000;
+ __el3_stack = .;
+ }
+
+ .ttb0_l1 (NOLOAD):
+ {
+ . = ALIGN(4096);
+ __ttb0_l1 = .;
+ . = . + 0x1000;
+ }
+
+ .ttb0_l2_ram (NOLOAD):
+ {
+ . = ALIGN(4096);
+ __ttb0_l2_ram = .;
+ . = . + 0x1000;
+ }
+
+ .ttb0_l2_private (NOLOAD):
+ {
+ . = ALIGN(4096);
+ __ttb0_l2_private = .;
+ . = . + 0x1000;
+ }
+
+ .ttb0_l2_periph (NOLOAD):
+ {
+ . = ALIGN(4096);
+ __ttb0_l2_periph = .;
+ . = . + 0x1000;
+ }
+
+ /*
+ * The startup code uses the end of this region to calculate
+ * the top of memory - don't place any RAM regions after it
+ */
+ __top_of_ram = .;
+}
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.c b/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.c
new file mode 100644
index 00000000..c2ce6faa
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.c
@@ -0,0 +1,122 @@
+// ------------------------------------------------------------
+// SP804 Dual Timer
+//
+// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+// ------------------------------------------------------------
+
+#include "sp804_timer.h"
+
+#define TIMER_SP804_CTRL_TIMEREN (1 << 7)
+#define TIMER_SP804_CTRL_TIMERMODE (1 << 6) // Bit 6:
+#define TIMER_SP804_CTRL_INTENABLE (1 << 5)
+#define TIMER_SP804_CTRL_TIMERSIZE (1 << 1) // Bit 1: 0=16-bit, 1=32-bit
+#define TIMER_SP804_CTRL_ONESHOT (1 << 0) // Bit 0: 0=wrapping, 1=one-shot
+
+#define TIMER_SP804_CTRL_PRESCALE_1 (0 << 2) // clk/1
+#define TIMER_SP804_CTRL_PRESCALE_4 (1 << 2) // clk/4
+#define TIMER_SP804_CTRL_PRESCALE_8 (2 << 2) // clk/8
+
+struct sp804_timer
+{
+ volatile uint32_t Time1Load; // +0x00
+ const volatile uint32_t Time1Value; // +0x04 - RO
+ volatile uint32_t Timer1Control; // +0x08
+ volatile uint32_t Timer1IntClr; // +0x0C - WO
+ const volatile uint32_t Timer1RIS; // +0x10 - RO
+ const volatile uint32_t Timer1MIS; // +0x14 - RO
+ volatile uint32_t Timer1BGLoad; // +0x18
+
+ volatile uint32_t Time2Load; // +0x20
+ volatile uint32_t Time2Value; // +0x24
+ volatile uint8_t Timer2Control; // +0x28
+ volatile uint32_t Timer2IntClr; // +0x2C - WO
+ const volatile uint32_t Timer2RIS; // +0x30 - RO
+ const volatile uint32_t Timer2MIS; // +0x34 - RO
+ volatile uint32_t Timer2BGLoad; // +0x38
+
+ // Not including ID registers
+
+};
+
+// Instance of the dual timer, will be placed using the scatter file
+struct sp804_timer* dual_timer;
+
+
+// Set base address of timer
+// address - virtual address of SP804 timer
+void setTimerBaseAddress(uint64_t address)
+{
+ dual_timer = (struct sp804_timer*)address;
+ return;
+}
+
+
+// Sets up the private timer
+// load_value - Initial value of timer
+// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
+// interrupt - Whether to generate an interrupt
+void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt)
+{
+ uint32_t tmp = 0;
+
+ dual_timer->Time1Load = load_value;
+
+ // Fixed setting: 32-bit, no prescaling
+ tmp = TIMER_SP804_CTRL_TIMERSIZE | TIMER_SP804_CTRL_PRESCALE_1 | TIMER_SP804_CTRL_TIMERMODE;
+
+ // Settings from parameters: interrupt generation & reload
+ tmp = tmp | interrupt | auto_reload;
+
+ // Write control register
+ dual_timer->Timer1Control = tmp;
+
+ return;
+}
+
+
+// Starts the timer
+void startTimer(void)
+{
+ uint32_t tmp;
+
+ tmp = dual_timer->Timer1Control;
+ tmp = tmp | TIMER_SP804_CTRL_TIMEREN; // Set TimerEn (bit 7)
+ dual_timer->Timer1Control = tmp;
+
+ return;
+}
+
+
+// Stops the timer
+void stopTimer(void)
+{
+ uint32_t tmp;
+
+ tmp = dual_timer->Timer1Control;
+ tmp = tmp & ~TIMER_SP804_CTRL_TIMEREN; // Clear TimerEn (bit 7)
+ dual_timer->Timer1Control = tmp;
+
+ return;
+}
+
+
+// Returns the current timer count
+uint32_t getTimerCount(void)
+{
+ return dual_timer->Time1Value;
+}
+
+
+void clearTimerIrq(void)
+{
+ // A write to this register, of any value, clears the interrupt
+ dual_timer->Timer1IntClr = 1;
+}
+
+
+// ------------------------------------------------------------
+// End of sp804_timer.c
+// ------------------------------------------------------------
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.h b/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.h
new file mode 100644
index 00000000..4d423904
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/sp804_timer.h
@@ -0,0 +1,53 @@
+// ------------------------------------------------------------
+// SP804 Dual Timer
+// Header Filer
+//
+// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+// ------------------------------------------------------------
+
+#ifndef _SP804_TIMER_
+#define _SP804_TIMER_
+
+#include <stdint.h>
+
+// Set base address of timer
+// address - virtual address of SP804 timer
+void setTimerBaseAddress(uint64_t address);
+
+
+// Sets up the private timer
+// load_value - Initial value of timer
+// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
+// interrupt - Whether to generate an interrupt
+
+#define SP804_AUTORELOAD (0)
+#define SP804_SINGLESHOT (1)
+#define SP804_GENERATE_IRQ (1 << 5)
+#define SP804_NO_IRQ (0)
+
+void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt);
+
+
+// Starts the timer
+void startTimer(void);
+
+
+// Stops the timer
+void stopTimer(void);
+
+
+// Returns the current timer count
+uint32_t getTimerCount(void);
+
+
+// Clears the timer interrupt
+void clearTimerIrq(void);
+
+#endif
+
+// ------------------------------------------------------------
+// End of sp804_timer.h
+// ------------------------------------------------------------
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/startup.S b/ports/cortex_a72/gnu/example_build/sample_threadx/startup.S
new file mode 100644
index 00000000..b71b45f8
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/startup.S
@@ -0,0 +1,787 @@
+// ------------------------------------------------------------
+// Armv8-A MPCore EL3 AArch64 Startup Code
+//
+// Basic Vectors, MMU, caches and GICv3 initialization
+//
+// Exits in EL1 AArch64
+//
+// Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+// ------------------------------------------------------------
+
+#include "v8_mmu.h"
+#include "v8_system.h"
+#include "GICv3_aliases.h"
+
+ .section StartUp, "ax"
+ .balign 4
+
+
+ .global el1_vectors
+ .global el2_vectors
+ .global el3_vectors
+
+ .global InvalidateUDCaches
+ .global ZeroBlock
+
+ .global SetPrivateIntSecurityBlock
+ .global SetSPISecurityAll
+ .global SetPrivateIntPriority
+
+ .global GetGICR
+ .global WakeupGICR
+ .global SyncAREinGICD
+ .global EnableGICD
+ .global EnablePrivateInt
+ .global GetPrivateIntPending
+ .global ClearPrivateIntPending
+
+ .global _start
+ .global MainApp
+
+ .global __code_start
+ .global __ttb0_l1
+ .global __ttb0_l2_ram
+ .global __ttb0_l2_periph
+ .global __top_of_ram
+ .global gicd
+ .global __stack
+ .global __el3_stack
+ .global __cs3_peripherals
+
+
+
+
+// ------------------------------------------------------------
+
+ .global start64
+ .type start64, "function"
+start64:
+
+ //
+ // program the VBARs
+ //
+ ldr x1, =el1_vectors
+ msr VBAR_EL1, x1
+
+ ldr x1, =el2_vectors
+ msr VBAR_EL2, x1
+
+ ldr x1, =el3_vectors
+ msr VBAR_EL3, x1
+
+
+ // GIC-500 comes out of reset in GICv2 compatibility mode - first set
+ // system register enables for all relevant exception levels, and
+ // select GICv3 operating mode
+ //
+ msr SCR_EL3, xzr // Ensure NS bit is initially clear, so secure copy of ICC_SRE_EL1 can be configured
+ isb
+
+ mov x0, #15
+ msr ICC_SRE_EL3, x0
+ isb
+ msr ICC_SRE_EL1, x0 // Secure copy of ICC_SRE_EL1
+
+ //
+ // set lower exception levels as non-secure, with no access
+ // back to EL2 or EL3, and are AArch64 capable
+ //
+ mov x3, #(SCR_EL3_RW | \
+ SCR_EL3_SMD | \
+ SCR_EL3_NS) // Set NS bit, to access Non-secure registers
+ msr SCR_EL3, x3
+ isb
+
+ mov x0, #15
+ msr ICC_SRE_EL2, x0
+ isb
+ msr ICC_SRE_EL1, x0 // Non-secure copy of ICC_SRE_EL1
+
+
+ //
+ // no traps or VM modifications from the Hypervisor, EL1 is AArch64
+ //
+ mov x2, #HCR_EL2_RW
+ msr HCR_EL2, x2
+
+ //
+ // VMID is still significant, even when virtualisation is not
+ // being used, so ensure VTTBR_EL2 is properly initialised
+ //
+ msr VTTBR_EL2, xzr
+
+ //
+ // VMPIDR_EL2 holds the value of the Virtualization Multiprocessor ID. This is the value returned by Non-secure EL1 reads of MPIDR_EL1.
+ // VPIDR_EL2 holds the value of the Virtualization Processor ID. This is the value returned by Non-secure EL1 reads of MIDR_EL1.
+ // Both of these registers are architecturally UNKNOWN at reset, and so they must be set to the correct value
+ // (even if EL2/virtualization is not being used), otherwise non-secure EL1 reads of MPIDR_EL1/MIDR_EL1 will return garbage values.
+ // This guarantees that any future reads of MPIDR_EL1 and MIDR_EL1 from Non-secure EL1 will return the correct value.
+ //
+ mrs x0, MPIDR_EL1
+ msr VMPIDR_EL2, x0
+ mrs x0, MIDR_EL1
+ msr VPIDR_EL2, x0
+
+ // extract the core number from MPIDR_EL1 and store it in
+ // x19 (defined by the AAPCS as callee-saved), so we can re-use
+ // the number later
+ //
+ bl GetCPUID
+ mov x19, x0
+
+ //
+ // neither EL3 nor EL2 trap floating point or accesses to CPACR
+ //
+ msr CPTR_EL3, xzr
+ msr CPTR_EL2, xzr
+
+ //
+ // SCTLR_ELx may come out of reset with UNKNOWN values so we will
+ // set the fields to 0 except, possibly, the endianess field(s).
+ // Note that setting SCTLR_EL2 or the EL0 related fields of SCTLR_EL1
+ // is not strictly needed, since we're never in EL2 or EL0
+ //
+#ifdef __ARM_BIG_ENDIAN
+ mov x0, #(SCTLR_ELx_EE | SCTLR_EL1_E0E)
+#else
+ mov x0, #0
+#endif
+ msr SCTLR_EL3, x0
+ msr SCTLR_EL2, x0
+ msr SCTLR_EL1, x0
+
+#ifdef CORTEXA
+ //
+ // Configure ACTLR_EL[23]
+ // ----------------------
+ //
+ // These bits are IMPLEMENTATION DEFINED, so are different for
+ // different processors
+ //
+ // For Cortex-A57, the controls we set are:
+ //
+ // Enable lower level access to CPUACTLR_EL1
+ // Enable lower level access to CPUECTLR_EL1
+ // Enable lower level access to L2CTLR_EL1
+ // Enable lower level access to L2ECTLR_EL1
+ // Enable lower level access to L2ACTLR_EL1
+ //
+ mov x0, #((1 << 0) | \
+ (1 << 1) | \
+ (1 << 4) | \
+ (1 << 5) | \
+ (1 << 6))
+
+ msr ACTLR_EL3, x0
+ msr ACTLR_EL2, x0
+
+ //
+ // configure CPUECTLR_EL1
+ //
+ // These bits are IMP DEF, so need to different for different
+ // processors
+ //
+ // SMPEN - bit 6 - Enables the processor to receive cache
+ // and TLB maintenance operations
+ //
+ // Note: For Cortex-A57/53 SMPEN should be set before enabling
+ // the caches and MMU, or performing any cache and TLB
+ // maintenance operations.
+ //
+ // This register has a defined reset value, so we use a
+ // read-modify-write sequence to set SMPEN
+ //
+ mrs x0, S3_1_c15_c2_1 // Read EL1 CPU Extended Control Register
+ orr x0, x0, #(1 << 6) // Set the SMPEN bit
+ msr S3_1_c15_c2_1, x0 // Write EL1 CPU Extended Control Register
+
+ isb
+#endif
+
+ //
+ // That's the last of the control settings for now
+ //
+ // Note: no ISB after all these changes, as registers won't be
+ // accessed until after an exception return, which is itself a
+ // context synchronisation event
+ //
+
+ //
+ // Setup some EL3 stack space, ready for calling some subroutines, below.
+ //
+ // Stack space allocation is CPU-specific, so use CPU
+ // number already held in x19
+ //
+ // 2^12 bytes per CPU for the EL3 stacks
+ //
+ ldr x0, =__el3_stack
+ sub x0, x0, x19, lsl #12
+ mov sp, x0
+
+ //
+ // we need to configure the GIC while still in secure mode, specifically
+ // all PPIs and SPIs have to be programmed as Group1 interrupts
+ //
+
+ //
+ // Before the GIC can be reliably programmed, we need to
+ // enable Affinity Routing, as this affects where the configuration
+ // registers are (with Affinity Routing enabled, some registers are
+ // in the Redistributor, whereas those same registers are in the
+ // Distributor with Affinity Routing disabled (i.e. when in GICv2
+ // compatibility mode).
+ //
+ mov x0, #(1 << 4) | (1 << 5) // gicdctlr_ARE_S | gicdctlr_ARE_NS
+ mov x1, x19
+ bl SyncAREinGICD
+
+ //
+ // The Redistributor comes out of reset assuming the processor is
+ // asleep - correct that assumption
+ //
+ bl GetAffinity
+ bl GetGICR
+ mov w20, w0 // Keep a copy for later
+ bl WakeupGICR
+
+ //
+ // Now we're ready to set security and other initialisations
+ //
+ // This is a per-CPU configuration for these interrupts
+ //
+ // for the first cluster, CPU number is the redistributor index
+ //
+ mov w0, w20
+ mov w1, #1 // gicigroupr_G1NS
+ bl SetPrivateIntSecurityBlock
+
+ //
+ // While we're in the Secure World, set the priority mask low enough
+ // for it to be writable in the Non-Secure World
+ //
+ //mov x0, #16 << 3 // 5 bits of priority in the Secure world
+ mov x0, #0xFF // for Non-Secure interrupts
+ msr ICC_PMR_EL1, x0
+
+ //
+ // there's more GIC setup to do, but only for the primary CPU
+ //
+ cbnz x19, drop_to_el1
+
+ //
+ // There's more to do to the GIC - call the utility routine to set
+ // all SPIs to Group1
+ //
+ mov w0, #1 // gicigroupr_G1NS
+ bl SetSPISecurityAll
+
+ //
+ // Set up EL1 entry point and "dummy" exception return information,
+ // then perform exception return to enter EL1
+ //
+ .global drop_to_el1
+drop_to_el1:
+ adr x1, el1_entry_aarch64
+ msr ELR_EL3, x1
+ mov x1, #(AARCH64_SPSR_EL1h | \
+ AARCH64_SPSR_F | \
+ AARCH64_SPSR_I | \
+ AARCH64_SPSR_A)
+ msr SPSR_EL3, x1
+ eret
+
+
+
+// ------------------------------------------------------------
+// EL1 - Common start-up code
+// ------------------------------------------------------------
+
+ .global el1_entry_aarch64
+ .type el1_entry_aarch64, "function"
+el1_entry_aarch64:
+
+ //
+ // Now we're in EL1, setup the application stack
+ // the scatter file allocates 2^14 bytes per app stack
+ //
+ ldr x0, =__handler_stack
+ sub x0, x0, x19, lsl #14
+ mov sp, x0
+ MSR SPSel, #0
+ ISB
+ ldr x0, =__stack
+ sub x0, x0, x19, lsl #14
+ mov sp, x0
+
+ //
+ // Enable floating point
+ //
+ mov x0, #CPACR_EL1_FPEN
+ msr CPACR_EL1, x0
+
+ //
+ // Invalidate caches and TLBs for all stage 1
+ // translations used at EL1
+ //
+ // Cortex-A processors automatically invalidate their caches on reset
+ // (unless suppressed with the DBGL1RSTDISABLE or L2RSTDISABLE pins).
+ // It is therefore not necessary for software to invalidate the caches
+ // on startup, however, this is done here in case of a warm reset.
+ bl InvalidateUDCaches
+ tlbi VMALLE1
+
+
+ //
+ // Set TTBR0 Base address
+ //
+ // The CPUs share one set of translation tables that are
+ // generated by CPU0 at run-time
+ //
+ // TTBR1_EL1 is not used in this example
+ //
+ ldr x1, =__ttb0_l1
+ msr TTBR0_EL1, x1
+
+
+ //
+ // Set up memory attributes
+ //
+ // These equate to:
+ //
+ // 0 -> 0b01000100 = 0x00000044 = Normal, Inner/Outer Non-Cacheable
+ // 1 -> 0b11111111 = 0x0000ff00 = Normal, Inner/Outer WriteBack Read/Write Allocate
+ // 2 -> 0b00000100 = 0x00040000 = Device-nGnRE
+ //
+ mov x1, #0xff44
+ movk x1, #4, LSL #16 // equiv to: movk x1, #0x0000000000040000
+ msr MAIR_EL1, x1
+
+
+ //
+ // Set up TCR_EL1
+ //
+ // We're using only TTBR0 (EPD1 = 1), and the page table entries:
+ // - are using an 8-bit ASID from TTBR0
+ // - have a 4K granularity (TG0 = 0b00)
+ // - are outer-shareable (SH0 = 0b10)
+ // - are using Inner & Outer WBWA Normal memory ([IO]RGN0 = 0b01)
+ // - map
+ // + 32 bits of VA space (T0SZ = 0x20)
+ // + into a 32-bit PA space (IPS = 0b000)
+ //
+ // 36 32 28 24 20 16 12 8 4 0
+ // -----+----+----+----+----+----+----+----+----+----+
+ // | | |OOII| | | |OOII| | |
+ // TT | | |RRRR|E T | T| |RRRR|E T | T|
+ // BB | I I|TTSS|GGGG|P 1 | 1|TTSS|GGGG|P 0 | 0|
+ // IIA| P P|GGHH|NNNN|DAS | S|GGHH|NNNN|D S | S|
+ // 10S| S-S|1111|1111|11Z-|---Z|0000|0000|0 Z-|---Z|
+ //
+ // 000 0000 0000 0000 1000 0000 0010 0101 0010 0000
+ //
+ // 0x 8 0 2 5 2 0
+ //
+ // Note: the ISB is needed to ensure the changes to system
+ // context are before the write of SCTLR_EL1.M to enable
+ // the MMU. It is likely on a "real" implementation that
+ // this setup would work without an ISB, due to the
+ // amount of code that gets executed before enabling the
+ // MMU, but that would not be architecturally correct.
+ //
+ ldr x1, =0x0000000000802520
+ msr TCR_EL1, x1
+ isb
+
+ //
+ // x19 already contains the CPU number, so branch to secondary
+ // code if we're not on CPU0
+ //
+ cbnz x19, el1_secondary
+
+ //
+ // Fall through to primary code
+ //
+
+
+//
+// ------------------------------------------------------------
+//
+// EL1 - primary CPU init code
+//
+// This code is run on CPU0, while the other CPUs are in the
+// holding pen
+//
+
+ .global el1_primary
+ .type el1_primary, "function"
+el1_primary:
+
+ //
+ // Turn on the banked GIC distributor enable,
+ // ready for individual CPU enables later
+ //
+ mov w0, #(1 << 1) // gicdctlr_EnableGrp1A
+ bl EnableGICD
+
+ //
+ // Generate TTBR0 L1
+ //
+ // at 4KB granularity, 32-bit VA space, table lookup starts at
+ // L1, with 1GB regions
+ //
+ // we are going to create entries pointing to L2 tables for a
+ // couple of these 1GB regions, the first of which is the
+ // RAM on the VE board model - get the table addresses and
+ // start by emptying out the L1 page tables (4 entries at L1
+ // for a 4K granularity)
+ //
+ // x21 = address of L1 tables
+ //
+ ldr x21, =__ttb0_l1
+ mov x0, x21
+ mov x1, #(4 << 3)
+ bl ZeroBlock
+
+ //
+ // time to start mapping the RAM regions - clear out the
+ // L2 tables and point to them from the L1 tables
+ //
+ // x22 = address of L2 tables, needs to be remembered in case
+ // we want to re-use the tables for mapping peripherals
+ //
+ ldr x22, =__ttb0_l2_ram
+ mov x1, #(512 << 3)
+ mov x0, x22
+ bl ZeroBlock
+
+ //
+ // Get the start address of RAM (the EXEC region) into x4
+ // and calculate the offset into the L1 table (1GB per region,
+ // max 4GB)
+ //
+ // x23 = L1 table offset, saved for later comparison against
+ // peripheral offset
+ //
+ ldr x4, =__code_start
+ ubfx x23, x4, #30, #2
+
+ orr x1, x22, #TT_S1_ATTR_PAGE
+ str x1, [x21, x23, lsl #3]
+
+ //
+ // we've already used the RAM start address in x4 - we now need
+ // to get this in terms of an offset into the L2 page tables,
+ // where each entry covers 2MB
+ //
+ ubfx x2, x4, #21, #9
+
+ //
+ // TOP_OF_RAM in the scatter file marks the end of the
+ // Execute region in RAM: convert the end of this region to an
+ // offset too, being careful to round up, then calculate the
+ // number of entries to write
+ //
+ ldr x5, =__top_of_ram
+ sub x3, x5, #1
+ ubfx x3, x3, #21, #9
+ add x3, x3, #1
+ sub x3, x3, x2
+
+ //
+ // set x1 to the required page table attributes, then orr
+ // in the start address (modulo 2MB)
+ //
+ // L2 tables in our configuration cover 2MB per entry - map
+ // memory as Shared, Normal WBWA (MAIR[1]) with a flat
+ // VA->PA translation
+ //
+ bic x4, x4, #((1 << 21) - 1)
+ ldr x1, =(TT_S1_ATTR_BLOCK | \
+ (1 << TT_S1_ATTR_MATTR_LSB) | \
+ TT_S1_ATTR_NS | \
+ TT_S1_ATTR_AP_RW_PL1 | \
+ TT_S1_ATTR_SH_INNER | \
+ TT_S1_ATTR_AF | \
+ TT_S1_ATTR_nG)
+ orr x1, x1, x4
+
+ //
+ // factor the offset into the page table address and then write
+ // the entries
+ //
+ add x0, x22, x2, lsl #3
+
+loop1:
+ subs x3, x3, #1
+ str x1, [x0], #8
+ add x1, x1, #0x200, LSL #12 // equiv to add x1, x1, #(1 << 21) // 2MB per entry
+ bne loop1
+
+
+ //
+ // now mapping the Peripheral regions - clear out the
+ // L2 tables and point to them from the L1 tables
+ //
+ // The assumption here is that all peripherals live within
+ // a common 1GB region (i.e. that there's a single set of
+ // L2 pages for all the peripherals). We only use a UART
+ // and the GIC in this example, so the assumption is sound
+ //
+ // x24 = address of L2 peripheral tables
+ //
+ ldr x24, =__ttb0_l2_periph
+
+ //
+ // get the GICD address into x4 and calculate
+ // the offset into the L1 table
+ //
+ // x25 = L1 table offset
+ //
+ ldr x4, =gicd
+ ubfx x25, x4, #30, #2
+
+ //
+ // here's the tricky bit: it's possible that the peripherals are
+ // in the same 1GB region as the RAM, in which case we don't need
+ // to prime a separate set of L2 page tables, nor add them to the
+ // L1 tables
+ //
+ // if we're going to re-use the TTB0_L2_RAM tables, get their
+ // address into x24, which is used later on to write the PTEs
+ //
+ cmp x25, x23
+ csel x24, x22, x24, EQ
+ b.eq nol2setup
+
+ //
+ // Peripherals are in a separate 1GB region, and so have their own
+ // set of L2 tables - clean out the tables and add them to the L1
+ // table
+ //
+ mov x0, x24
+ mov x1, #512 << 3
+ bl ZeroBlock
+
+ orr x1, x24, #TT_S1_ATTR_PAGE
+ str x1, [x21, x25, lsl #3]
+
+ //
+ // there's only going to be a single 2MB region for GICD (in
+ // x4) - get this in terms of an offset into the L2 page tables
+ //
+ // with larger systems, it is possible that the GIC redistributor
+ // registers require extra 2MB pages, in which case extra code
+ // would be required here
+ //
+nol2setup:
+ ubfx x2, x4, #21, #9
+
+ //
+ // set x1 to the required page table attributes, then orr
+ // in the start address (modulo 2MB)
+ //
+ // L2 tables in our configuration cover 2MB per entry - map
+ // memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
+ // translation
+ //
+ bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
+ ldr x1, =(TT_S1_ATTR_BLOCK | \
+ (2 << TT_S1_ATTR_MATTR_LSB) | \
+ TT_S1_ATTR_NS | \
+ TT_S1_ATTR_AP_RW_PL1 | \
+ TT_S1_ATTR_AF | \
+ TT_S1_ATTR_nG)
+ orr x1, x1, x4
+
+ //
+ // only a single L2 entry for this, so no loop as we have for RAM, above
+ //
+ str x1, [x24, x2, lsl #3]
+
+ //
+ // we have CS3_PERIPHERALS that include the UART controller
+ //
+ // Again, the code is making assumptions - this time that the CS3_PERIPHERALS
+ // region uses the same 1GB portion of the address space as the GICD,
+ // and thus shares the same set of L2 page tables
+ //
+ // Get CS3_PERIPHERALS address into x4 and calculate the offset into the
+ // L2 tables
+ //
+ ldr x4, =__cs3_peripherals
+ ubfx x2, x4, #21, #9
+
+ //
+ // set x1 to the required page table attributes, then orr
+ // in the start address (modulo 2MB)
+ //
+ // L2 tables in our configuration cover 2MB per entry - map
+ // memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
+ // translation
+ //
+ bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
+ ldr x1, =(TT_S1_ATTR_BLOCK | \
+ (2 << TT_S1_ATTR_MATTR_LSB) | \
+ TT_S1_ATTR_NS | \
+ TT_S1_ATTR_AP_RW_PL1 | \
+ TT_S1_ATTR_AF | \
+ TT_S1_ATTR_nG)
+ orr x1, x1, x4
+
+ //
+ // only a single L2 entry again - write it
+ //
+ str x1, [x24, x2, lsl #3]
+
+ //
+ // issue a barrier to ensure all table entry writes are complete
+ //
+ dsb ish
+
+ //
+ // Enable the MMU. Caches will be enabled later, after scatterloading.
+ //
+ mrs x1, SCTLR_EL1
+ orr x1, x1, #SCTLR_ELx_M
+ bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
+ msr SCTLR_EL1, x1
+ isb
+
+ //
+ // The Arm Architecture Reference Manual for Armv8-A states:
+ //
+ // Instruction accesses to Non-cacheable Normal memory can be held in instruction caches.
+ // Correspondingly, the sequence for ensuring that modifications to instructions are available
+ // for execution must include invalidation of the modified locations from the instruction cache,
+ // even if the instructions are held in Normal Non-cacheable memory.
+ // This includes cases where the instruction cache is disabled.
+ //
+
+ dsb ish // ensure all previous stores have completed before invalidating
+ ic ialluis // I cache invalidate all inner shareable to PoU (which includes secondary cores)
+ dsb ish // ensure completion on inner shareable domain (which includes secondary cores)
+ isb
+
+ // Scatter-loading is complete, so enable the caches here, so that the C-library's mutex initialization later will work
+ mrs x1, SCTLR_EL1
+ orr x1, x1, #SCTLR_ELx_C
+ orr x1, x1, #SCTLR_ELx_I
+ msr SCTLR_EL1, x1
+ isb
+
+ // Zero the bss
+ ldr x0, =__bss_start__ // Start of block
+ mov x1, #0 // Fill value
+ ldr x2, =__bss_end__ // End of block
+ sub x2, x2, x0 // Length of block
+ bl memset
+
+ // Set up the standard file handles
+ bl initialise_monitor_handles
+
+ // Set up _fini and fini_array to be called at exit
+ ldr x0, =__libc_fini_array
+ bl atexit
+
+ // Call preinit_array, _init and init_array
+ bl __libc_init_array
+
+ // Set argc = 1, argv[0] = "" and then call main
+ .pushsection .data
+ .align 3
+argv:
+ .dword arg0
+ .dword 0
+arg0:
+ .byte 0
+ .popsection
+
+ mov x0, #1
+ ldr x1, =argv
+ bl main
+
+ b exit // Will not return
+
+// ------------------------------------------------------------
+// EL1 - secondary CPU init code
+//
+// This code is run on CPUs 1, 2, 3 etc....
+// ------------------------------------------------------------
+
+ .global el1_secondary
+ .type el1_secondary, "function"
+el1_secondary:
+
+ //
+ // the primary CPU is going to use SGI 15 as a wakeup event
+ // to let us know when it is OK to proceed, so prepare for
+ // receiving that interrupt
+ //
+ // NS interrupt priorities run from 0 to 15, with 15 being
+ // too low a priority to ever raise an interrupt, so let's
+ // use 14
+ //
+ mov w0, w20
+ mov w1, #15
+ mov w2, #14 << 4 // we're in NS world, so 4 bits of priority,
+ // 8-bit field, - 4 = 4-bit shift
+ bl SetPrivateIntPriority
+
+ mov w0, w20
+ mov w1, #15
+ bl EnablePrivateInt
+
+ //
+ // set priority mask as low as possible; although,being in the
+ // NS World, we can't set bit[7] of the priority, we still
+ // write all 8-bits of priority to an ICC register
+ //
+ mov x0, #31 << 3
+ msr ICC_PMR_EL1, x0
+
+ //
+ // set global enable and wait for our interrupt to arrive
+ //
+ mov x0, #1
+ msr ICC_IGRPEN1_EL1, x0
+ isb
+
+loop_wfi:
+ dsb SY // Clear all pending data accesses
+ wfi // Go to sleep
+
+ //
+ // something woke us from our wait, was it the required interrupt?
+ //
+ mov w0, w20
+ mov w1, #15
+ bl GetPrivateIntPending
+ cbz w0, loop_wfi
+
+ //
+ // it was - there's no need to actually take the interrupt,
+ // so just clear it
+ //
+ mov w0, w20
+ mov w1, #15
+ bl ClearPrivateIntPending
+
+ //
+ // Enable the MMU and caches
+ //
+ mrs x1, SCTLR_EL1
+ orr x1, x1, #SCTLR_ELx_M
+ orr x1, x1, #SCTLR_ELx_C
+ orr x1, x1, #SCTLR_ELx_I
+ bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
+ msr SCTLR_EL1, x1
+ isb
+
+ //
+ // Branch to thread start
+ //
+ //B MainApp
+
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/timer_interrupts.c b/ports/cortex_a72/gnu/example_build/sample_threadx/timer_interrupts.c
new file mode 100644
index 00000000..8f522217
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/timer_interrupts.c
@@ -0,0 +1,152 @@
+/* Bare-metal example for Armv8-A FVP Base model */
+
+/* Timer and interrupts */
+
+/* Copyright (c) 2016-2018 Arm Limited (or its affiliates). All rights reserved. */
+/* Use, modification and redistribution of this file is subject to your possession of a */
+/* valid End User License Agreement for the Arm Product of which these examples are part of */
+/* and your compliance with all applicable terms and conditions of such licence agreement. */
+
+#include <stdio.h>
+
+#include "GICv3.h"
+#include "GICv3_gicc.h"
+#include "sp804_timer.h"
+
+void _tx_timer_interrupt(void);
+
+// LED Base address
+#define LED_BASE (volatile unsigned int *)0x1C010008
+
+
+void nudge_leds(void) // Move LEDs along
+{
+ static int state = 1;
+ static int value = 1;
+
+ if (state)
+ {
+ int max = (1 << 7);
+ value <<= 1;
+ if (value == max)
+ state = 0;
+ }
+ else
+ {
+ value >>= 1;
+ if (value == 1)
+ state = 1;
+ }
+
+ *LED_BASE = value; // Update LEDs hardware
+}
+
+
+// Initialize Timer 0 and Interrupt Controller
+void init_timer(void)
+{
+ // Enable interrupts
+ __asm("MSR DAIFClr, #0xF");
+ setICC_IGRPEN1_EL1(igrpEnable);
+
+ // Configure the SP804 timer to generate an interrupt
+ setTimerBaseAddress(0x1C110000);
+ initTimer(0x200, SP804_AUTORELOAD, SP804_GENERATE_IRQ);
+ startTimer();
+
+ // The SP804 timer generates SPI INTID 34. Enable
+ // this ID, and route it to core 0.0.0.0 (this one!)
+ SetSPIRoute(34, 0, gicdirouter_ModeSpecific); // Route INTID 34 to 0.0.0.0 (this core)
+ SetSPIPriority(34, 0); // Set INTID 34 to priority to 0
+ ConfigureSPI(34, gicdicfgr_Level); // Set INTID 34 as level-sensitive
+ EnableSPI(34); // Enable INTID 34
+}
+
+
+// --------------------------------------------------------
+
+void irqHandler(void)
+{
+ unsigned int ID;
+
+ ID = getICC_IAR1(); // readIntAck();
+
+ // Check for reserved IDs
+ if ((1020 <= ID) && (ID <= 1023))
+ {
+ //printf("irqHandler() - Reserved INTID %d\n\n", ID);
+ return;
+ }
+
+ switch(ID)
+ {
+ case 34:
+ // Dual-Timer 0 (SP804)
+ //printf("irqHandler() - External timer interrupt\n\n");
+ nudge_leds();
+ clearTimerIrq();
+
+ /* Call ThreadX timer interrupt processing. */
+ _tx_timer_interrupt();
+
+ break;
+
+ default:
+ // Unexpected ID value
+ //printf("irqHandler() - Unexpected INTID %d\n\n", ID);
+ break;
+ }
+
+ // Write the End of Interrupt register to tell the GIC
+ // we've finished handling the interrupt
+ setICC_EOIR1(ID); // writeAliasedEOI(ID);
+}
+
+// --------------------------------------------------------
+
+// Not actually used in this example, but provided for completeness
+
+void fiqHandler(void)
+{
+ unsigned int ID;
+ unsigned int aliased = 0;
+
+ ID = getICC_IAR0(); // readIntAck();
+ //printf("fiqHandler() - Read %d from IAR0\n", ID);
+
+ // Check for reserved IDs
+ if ((1020 <= ID) && (ID <= 1023))
+ {
+ //printf("fiqHandler() - Reserved INTID %d\n\n", ID);
+ ID = getICC_IAR1(); // readAliasedIntAck();
+ //printf("fiqHandler() - Read %d from AIAR\n", ID);
+ aliased = 1;
+
+ // If still spurious then simply return
+ if ((1020 <= ID) && (ID <= 1023))
+ return;
+ }
+
+ switch(ID)
+ {
+ case 34:
+ // Dual-Timer 0 (SP804)
+ //printf("fiqHandler() - External timer interrupt\n\n");
+ clearTimerIrq();
+ break;
+
+ default:
+ // Unexpected ID value
+ //printf("fiqHandler() - Unexpected INTID %d\n\n", ID);
+ break;
+ }
+
+ // Write the End of Interrupt register to tell the GIC
+ // we've finished handling the interrupt
+ // NOTE: If the ID was read from the Aliased IAR, then
+ // the aliased EOI register must be used
+ if (aliased == 0)
+ setICC_EOIR0(ID); // writeEOI(ID);
+ else
+ setICC_EOIR1(ID); // writeAliasedEOI(ID);
+}
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/use_model_semihosting.ds b/ports/cortex_a72/gnu/example_build/sample_threadx/use_model_semihosting.ds
new file mode 100644
index 00000000..6fde52b2
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/use_model_semihosting.ds
@@ -0,0 +1 @@
+set semihosting enabled off
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.S b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.S
new file mode 100644
index 00000000..45445a98
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.S
@@ -0,0 +1,179 @@
+// ------------------------------------------------------------
+// Armv8-A AArch64 - Common helper functions
+//
+// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+// ------------------------------------------------------------
+
+#include "v8_system.h"
+
+ .text
+ .cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
+
+ .global EnableCachesEL1
+ .global DisableCachesEL1
+ .global InvalidateUDCaches
+ .global GetMIDR
+ .global GetMPIDR
+ .global GetAffinity
+ .global GetCPUID
+
+// ------------------------------------------------------------
+
+//
+// void EnableCachesEL1(void)
+//
+// enable Instruction and Data caches
+//
+ .type EnableCachesEL1, "function"
+ .cfi_startproc
+EnableCachesEL1:
+
+ mrs x0, SCTLR_EL1
+ orr x0, x0, #SCTLR_ELx_I
+ orr x0, x0, #SCTLR_ELx_C
+ msr SCTLR_EL1, x0
+
+ isb
+ ret
+ .cfi_endproc
+
+
+// ------------------------------------------------------------
+
+ .type DisableCachesEL1, "function"
+ .cfi_startproc
+DisableCachesEL1:
+
+ mrs x0, SCTLR_EL1
+ bic x0, x0, #SCTLR_ELx_I
+ bic x0, x0, #SCTLR_ELx_C
+ msr SCTLR_EL1, x0
+
+ isb
+ ret
+ .cfi_endproc
+
+
+// ------------------------------------------------------------
+
+//
+// void InvalidateUDCaches(void)
+//
+// Invalidate data and unified caches
+//
+ .type InvalidateUDCaches, "function"
+ .cfi_startproc
+InvalidateUDCaches:
+ // From the Armv8-A Architecture Reference Manual
+
+ dmb ish // ensure all prior inner-shareable accesses have been observed
+
+ mrs x0, CLIDR_EL1
+ and w3, w0, #0x07000000 // get 2 x level of coherence
+ lsr w3, w3, #23
+ cbz w3, finished
+ mov w10, #0 // w10 = 2 x cache level
+ mov w8, #1 // w8 = constant 0b1
+loop_level:
+ add w2, w10, w10, lsr #1 // calculate 3 x cache level
+ lsr w1, w0, w2 // extract 3-bit cache type for this level
+ and w1, w1, #0x7
+ cmp w1, #2
+ b.lt next_level // no data or unified cache at this level
+ msr CSSELR_EL1, x10 // select this cache level
+ isb // synchronize change of csselr
+ mrs x1, CCSIDR_EL1 // read ccsidr
+ and w2, w1, #7 // w2 = log2(linelen)-4
+ add w2, w2, #4 // w2 = log2(linelen)
+ ubfx w4, w1, #3, #10 // w4 = max way number, right aligned
+ clz w5, w4 // w5 = 32-log2(ways), bit position of way in dc operand
+ lsl w9, w4, w5 // w9 = max way number, aligned to position in dc operand
+ lsl w16, w8, w5 // w16 = amount to decrement way number per iteration
+loop_way:
+ ubfx w7, w1, #13, #15 // w7 = max set number, right aligned
+ lsl w7, w7, w2 // w7 = max set number, aligned to position in dc operand
+ lsl w17, w8, w2 // w17 = amount to decrement set number per iteration
+loop_set:
+ orr w11, w10, w9 // w11 = combine way number and cache number ...
+ orr w11, w11, w7 // ... and set number for dc operand
+ dc isw, x11 // do data cache invalidate by set and way
+ subs w7, w7, w17 // decrement set number
+ b.ge loop_set
+ subs x9, x9, x16 // decrement way number
+ b.ge loop_way
+next_level:
+ add w10, w10, #2 // increment 2 x cache level
+ cmp w3, w10
+ b.gt loop_level
+ dsb sy // ensure completion of previous cache maintenance operation
+ isb
+finished:
+ ret
+ .cfi_endproc
+
+
+// ------------------------------------------------------------
+
+//
+// ID Register functions
+//
+
+ .type GetMIDR, "function"
+ .cfi_startproc
+GetMIDR:
+
+ mrs x0, MIDR_EL1
+ ret
+ .cfi_endproc
+
+
+ .type GetMPIDR, "function"
+ .cfi_startproc
+GetMPIDR:
+
+ mrs x0, MPIDR_EL1
+ ret
+ .cfi_endproc
+
+
+ .type GetAffinity, "function"
+ .cfi_startproc
+GetAffinity:
+
+ mrs x0, MPIDR_EL1
+ ubfx x1, x0, #32, #8
+ bfi w0, w1, #24, #8
+ ret
+ .cfi_endproc
+
+
+ .type GetCPUID, "function"
+ .cfi_startproc
+GetCPUID:
+
+ mrs x0, MIDR_EL1
+ ubfx x0, x0, #4, #12 // extract PartNum
+ cmp x0, #0xD0D // Cortex-A77
+ b.eq DynamIQ
+ cmp x0, #0xD0B // Cortex-A76
+ b.eq DynamIQ
+ cmp x0, #0xD0A // Cortex-A75
+ b.eq DynamIQ
+ cmp x0, #0xD05 // Cortex-A55
+ b.eq DynamIQ
+ b Others
+DynamIQ:
+ mrs x0, MPIDR_EL1
+ ubfx x0, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
+ ret
+
+Others:
+ mrs x0, MPIDR_EL1
+ ubfx x1, x0, #MPIDR_EL1_AFF0_LSB, #MPIDR_EL1_AFF_WIDTH
+ ubfx x2, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
+ add x0, x1, x2, LSL #2
+ ret
+ .cfi_endproc
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.h b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.h
new file mode 100644
index 00000000..b09079a4
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_aarch64.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * Armv8-A AArch64 common helper functions
+ *
+ * Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
+ * Use, modification and redistribution of this file is subject to your possession of a
+ * valid End User License Agreement for the Arm Product of which these examples are part of
+ * and your compliance with all applicable terms and conditions of such licence agreement.
+ */
+
+#ifndef V8_AARCH64_H
+#define V8_AARCH64_H
+
+/*
+ * Parameters for data barriers
+ */
+#define OSHLD 1
+#define OSHST 2
+#define OSH 3
+#define NSHLD 5
+#define NSHST 6
+#define NSH 7
+#define ISHLD 9
+#define ISHST 10
+#define ISH 11
+#define LD 13
+#define ST 14
+#define SY 15
+
+/**********************************************************************/
+
+/*
+ * function prototypes
+ */
+
+/*
+ * void InvalidateUDCaches(void)
+ * invalidates all Unified and Data Caches
+ *
+ * Inputs
+ * <none>
+ *
+ * Returns
+ * <nothing>
+ *
+ * Side Effects
+ * guarantees that all levels of cache will be invalidated before
+ * returning to caller
+ */
+void InvalidateUDCaches(void);
+
+/*
+ * unsigned long long EnableCachesEL1(void)
+ * enables I- and D- caches at EL1
+ *
+ * Inputs
+ * <none>
+ *
+ * Returns
+ * New value of SCTLR_EL1
+ *
+ * Side Effects
+ * context will be synchronised before returning to caller
+ */
+unsigned long long EnableCachesEL1(void);
+
+/*
+ * unsigned long long GetMIDR(void)
+ * returns the contents of MIDR_EL0
+ *
+ * Inputs
+ * <none>
+ *
+ * Returns
+ * MIDR_EL0
+ */
+unsigned long long GetMIDR(void);
+
+/*
+ * unsigned long long GetMPIDR(void)
+ * returns the contents of MPIDR_EL0
+ *
+ * Inputs
+ * <none>
+ *
+ * Returns
+ * MPIDR_EL0
+ */
+unsigned long long GetMPIDR(void);
+
+/*
+ * unsigned int GetCPUID(void)
+ * returns the Aff0 field of MPIDR_EL0
+ *
+ * Inputs
+ * <none>
+ *
+ * Returns
+ * MPIDR_EL0[7:0]
+ */
+unsigned int GetCPUID(void);
+
+#endif
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/v8_mmu.h b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_mmu.h
new file mode 100644
index 00000000..bce62b54
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_mmu.h
@@ -0,0 +1,128 @@
+//
+// Defines for v8 Memory Model
+//
+// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+#ifndef V8_MMU_H
+#define V8_MMU_H
+
+//
+// Translation Control Register fields
+//
+// RGN field encodings
+//
+#define TCR_RGN_NC 0b00
+#define TCR_RGN_WBWA 0b01
+#define TCR_RGN_WT 0b10
+#define TCR_RGN_WBRA 0b11
+
+//
+// Shareability encodings
+//
+#define TCR_SHARE_NONE 0b00
+#define TCR_SHARE_OUTER 0b10
+#define TCR_SHARE_INNER 0b11
+
+//
+// Granule size encodings
+//
+#define TCR_GRANULE_4K 0b00
+#define TCR_GRANULE_64K 0b01
+#define TCR_GRANULE_16K 0b10
+
+//
+// Physical Address sizes
+//
+#define TCR_SIZE_4G 0b000
+#define TCR_SIZE_64G 0b001
+#define TCR_SIZE_1T 0b010
+#define TCR_SIZE_4T 0b011
+#define TCR_SIZE_16T 0b100
+#define TCR_SIZE_256T 0b101
+
+//
+// Translation Control Register fields
+//
+#define TCR_EL1_T0SZ_SHIFT 0
+#define TCR_EL1_EPD0 (1 << 7)
+#define TCR_EL1_IRGN0_SHIFT 8
+#define TCR_EL1_ORGN0_SHIFT 10
+#define TCR_EL1_SH0_SHIFT 12
+#define TCR_EL1_TG0_SHIFT 14
+
+#define TCR_EL1_T1SZ_SHIFT 16
+#define TCR_EL1_A1 (1 << 22)
+#define TCR_EL1_EPD1 (1 << 23)
+#define TCR_EL1_IRGN1_SHIFT 24
+#define TCR_EL1_ORGN1_SHIFT 26
+#define TCR_EL1_SH1_SHIFT 28
+#define TCR_EL1_TG1_SHIFT 30
+#define TCR_EL1_IPS_SHIFT 32
+#define TCR_EL1_AS (1 << 36)
+#define TCR_EL1_TBI0 (1 << 37)
+#define TCR_EL1_TBI1 (1 << 38)
+
+//
+// Stage 1 Translation Table descriptor fields
+//
+#define TT_S1_ATTR_FAULT (0b00 << 0)
+#define TT_S1_ATTR_BLOCK (0b01 << 0) // Level 1/2
+#define TT_S1_ATTR_TABLE (0b11 << 0) // Level 0/1/2
+#define TT_S1_ATTR_PAGE (0b11 << 0) // Level 3
+
+#define TT_S1_ATTR_MATTR_LSB 2
+
+#define TT_S1_ATTR_NS (1 << 5)
+
+#define TT_S1_ATTR_AP_RW_PL1 (0b00 << 6)
+#define TT_S1_ATTR_AP_RW_ANY (0b01 << 6)
+#define TT_S1_ATTR_AP_RO_PL1 (0b10 << 6)
+#define TT_S1_ATTR_AP_RO_ANY (0b11 << 6)
+
+#define TT_S1_ATTR_SH_NONE (0b00 << 8)
+#define TT_S1_ATTR_SH_OUTER (0b10 << 8)
+#define TT_S1_ATTR_SH_INNER (0b11 << 8)
+
+#define TT_S1_ATTR_AF (1 << 10)
+#define TT_S1_ATTR_nG (1 << 11)
+
+// OA bits [15:12] - If Armv8.2-LPA is implemented, bits[15:12] are bits[51:48]
+// and bits[47:16] are bits[47:16] of the output address for a page of memory
+
+#define TT_S1_ATTR_nT (1 << 16) // Present if Armv8.4-TTRem is implemented, otherwise RES0
+
+#define TT_S1_ATTR_DBM (1 << 51) // Present if Armv8.1-TTHM is implemented, otherwise RES0
+
+#define TT_S1_ATTR_CONTIG (1 << 52)
+#define TT_S1_ATTR_PXN (1 << 53)
+#define TT_S1_ATTR_UXN (1 << 54)
+
+// PBHA bits[62:59] - If Armv8.2-TTPBHA is implemented, hardware can use these bits
+// for IMPLEMENTATIONDEFINED purposes, otherwise IGNORED
+
+#define TT_S1_MAIR_DEV_nGnRnE 0b00000000
+#define TT_S1_MAIR_DEV_nGnRE 0b00000100
+#define TT_S1_MAIR_DEV_nGRE 0b00001000
+#define TT_S1_MAIR_DEV_GRE 0b00001100
+
+//
+// Inner and Outer Normal memory attributes use the same bit patterns
+// Outer attributes just need to be shifted up
+//
+#define TT_S1_MAIR_OUTER_SHIFT 4
+
+#define TT_S1_MAIR_WT_TRANS_RA 0b0010
+
+#define TT_S1_MAIR_WB_TRANS_RA 0b0110
+#define TT_S1_MAIR_WB_TRANS_RWA 0b0111
+
+#define TT_S1_MAIR_WT_RA 0b1010
+
+#define TT_S1_MAIR_WB_RA 0b1110
+#define TT_S1_MAIR_WB_RWA 0b1111
+
+#endif // V8_MMU_H
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/v8_system.h b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_system.h
new file mode 100644
index 00000000..a62d2a33
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_system.h
@@ -0,0 +1,115 @@
+//
+// Defines for v8 System Registers
+//
+// Copyright (c) 2012-2016 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+#ifndef V8_SYSTEM_H
+#define V8_SYSTEM_H
+
+//
+// AArch64 SPSR
+//
+#define AARCH64_SPSR_EL3h 0b1101
+#define AARCH64_SPSR_EL3t 0b1100
+#define AARCH64_SPSR_EL2h 0b1001
+#define AARCH64_SPSR_EL2t 0b1000
+#define AARCH64_SPSR_EL1h 0b0101
+#define AARCH64_SPSR_EL1t 0b0100
+#define AARCH64_SPSR_EL0t 0b0000
+#define AARCH64_SPSR_RW (1 << 4)
+#define AARCH64_SPSR_F (1 << 6)
+#define AARCH64_SPSR_I (1 << 7)
+#define AARCH64_SPSR_A (1 << 8)
+#define AARCH64_SPSR_D (1 << 9)
+#define AARCH64_SPSR_IL (1 << 20)
+#define AARCH64_SPSR_SS (1 << 21)
+#define AARCH64_SPSR_V (1 << 28)
+#define AARCH64_SPSR_C (1 << 29)
+#define AARCH64_SPSR_Z (1 << 30)
+#define AARCH64_SPSR_N (1 << 31)
+
+//
+// Multiprocessor Affinity Register
+//
+#define MPIDR_EL1_AFF3_LSB 32
+#define MPIDR_EL1_U (1 << 30)
+#define MPIDR_EL1_MT (1 << 24)
+#define MPIDR_EL1_AFF2_LSB 16
+#define MPIDR_EL1_AFF1_LSB 8
+#define MPIDR_EL1_AFF0_LSB 0
+#define MPIDR_EL1_AFF_WIDTH 8
+
+//
+// Data Cache Zero ID Register
+//
+#define DCZID_EL0_BS_LSB 0
+#define DCZID_EL0_BS_WIDTH 4
+#define DCZID_EL0_DZP_LSB 5
+#define DCZID_EL0_DZP (1 << 5)
+
+//
+// System Control Register
+//
+#define SCTLR_EL1_UCI (1 << 26)
+#define SCTLR_ELx_EE (1 << 25)
+#define SCTLR_EL1_E0E (1 << 24)
+#define SCTLR_ELx_WXN (1 << 19)
+#define SCTLR_EL1_nTWE (1 << 18)
+#define SCTLR_EL1_nTWI (1 << 16)
+#define SCTLR_EL1_UCT (1 << 15)
+#define SCTLR_EL1_DZE (1 << 14)
+#define SCTLR_ELx_I (1 << 12)
+#define SCTLR_EL1_UMA (1 << 9)
+#define SCTLR_EL1_SED (1 << 8)
+#define SCTLR_EL1_ITD (1 << 7)
+#define SCTLR_EL1_THEE (1 << 6)
+#define SCTLR_EL1_CP15BEN (1 << 5)
+#define SCTLR_EL1_SA0 (1 << 4)
+#define SCTLR_ELx_SA (1 << 3)
+#define SCTLR_ELx_C (1 << 2)
+#define SCTLR_ELx_A (1 << 1)
+#define SCTLR_ELx_M (1 << 0)
+
+//
+// Architectural Feature Access Control Register
+//
+#define CPACR_EL1_TTA (1 << 28)
+#define CPACR_EL1_FPEN (3 << 20)
+
+//
+// Architectural Feature Trap Register
+//
+#define CPTR_ELx_TCPAC (1 << 31)
+#define CPTR_ELx_TTA (1 << 20)
+#define CPTR_ELx_TFP (1 << 10)
+
+//
+// Secure Configuration Register
+//
+#define SCR_EL3_TWE (1 << 13)
+#define SCR_EL3_TWI (1 << 12)
+#define SCR_EL3_ST (1 << 11)
+#define SCR_EL3_RW (1 << 10)
+#define SCR_EL3_SIF (1 << 9)
+#define SCR_EL3_HCE (1 << 8)
+#define SCR_EL3_SMD (1 << 7)
+#define SCR_EL3_EA (1 << 3)
+#define SCR_EL3_FIQ (1 << 2)
+#define SCR_EL3_IRQ (1 << 1)
+#define SCR_EL3_NS (1 << 0)
+
+//
+// Hypervisor Configuration Register
+//
+#define HCR_EL2_ID (1 << 33)
+#define HCR_EL2_CD (1 << 32)
+#define HCR_EL2_RW (1 << 31)
+#define HCR_EL2_TRVM (1 << 30)
+#define HCR_EL2_HVC (1 << 29)
+#define HCR_EL2_TDZ (1 << 28)
+
+#endif // V8_SYSTEM_H
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/v8_utils.S b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_utils.S
new file mode 100644
index 00000000..888892a0
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/v8_utils.S
@@ -0,0 +1,69 @@
+//
+// Simple utility routines for baremetal v8 code
+//
+// Copyright (c) 2013-2017 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+//
+
+#include "v8_system.h"
+
+ .text
+ .cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
+
+//
+// void *ZeroBlock(void *blockPtr, unsigned int nBytes)
+//
+// Zero fill a block of memory
+// Fill memory pages or similar structures with zeros.
+// The byte count must be a multiple of the block fill size (16 bytes)
+//
+// Inputs:
+// blockPtr - base address of block to fill
+// nBytes - block size, in bytes
+//
+// Returns:
+// pointer to just filled block, NULL if nBytes is
+// incompatible with block fill size
+//
+ .global ZeroBlock
+ .type ZeroBlock, "function"
+ .cfi_startproc
+ZeroBlock:
+
+ //
+ // we fill data by steam, 16 bytes at a time: check that
+ // blocksize is a multiple of that
+ //
+ ubfx x2, x1, #0, #4
+ cbnz x2, incompatible
+
+ //
+ // we already have one register full of zeros, get another
+ //
+ mov x3, x2
+
+ //
+ // OK, set temporary pointer and away we go
+ //
+ add x0, x0, x1
+
+loop0:
+ subs x1, x1, #16
+ stp x2, x3, [x0, #-16]!
+ b.ne loop0
+
+ //
+ // that's all - x0 will be back to its start value
+ //
+ ret
+
+ //
+ // parameters are incompatible with block size - return
+ // an indication that this is so
+ //
+incompatible:
+ mov x0,#0
+ ret
+ .cfi_endproc
diff --git a/ports/cortex_a72/gnu/example_build/sample_threadx/vectors.S b/ports/cortex_a72/gnu/example_build/sample_threadx/vectors.S
new file mode 100644
index 00000000..7784f98e
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/sample_threadx/vectors.S
@@ -0,0 +1,252 @@
+// ------------------------------------------------------------
+// Armv8-A Vector tables
+//
+// Copyright (c) 2014-2016 Arm Limited (or its affiliates). All rights reserved.
+// Use, modification and redistribution of this file is subject to your possession of a
+// valid End User License Agreement for the Arm Product of which these examples are part of
+// and your compliance with all applicable terms and conditions of such licence agreement.
+// ------------------------------------------------------------
+
+
+ .global el1_vectors
+ .global el2_vectors
+ .global el3_vectors
+ .global c0sync1
+ .global irqHandler
+ .global fiqHandler
+ .global irqFirstLevelHandler
+ .global fiqFirstLevelHandler
+
+ .section EL1VECTORS, "ax"
+ .align 11
+
+//
+// Current EL with SP0
+//
+el1_vectors:
+c0sync1: B c0sync1
+
+ .balign 0x80
+c0irq1: B irqFirstLevelHandler
+
+ .balign 0x80
+c0fiq1: B fiqFirstLevelHandler
+
+ .balign 0x80
+c0serr1: B c0serr1
+
+//
+// Current EL with SPx
+//
+ .balign 0x80
+cxsync1: B cxsync1
+
+ .balign 0x80
+cxirq1: B irqFirstLevelHandler
+
+ .balign 0x80
+cxfiq1: B fiqFirstLevelHandler
+
+ .balign 0x80
+cxserr1: B cxserr1
+
+//
+// Lower EL using AArch64
+//
+ .balign 0x80
+l64sync1: B l64sync1
+
+ .balign 0x80
+l64irq1: B irqFirstLevelHandler
+
+ .balign 0x80
+l64fiq1: B fiqFirstLevelHandler
+
+ .balign 0x80
+l64serr1: B l64serr1
+
+//
+// Lower EL using AArch32
+//
+ .balign 0x80
+l32sync1: B l32sync1
+
+ .balign 0x80
+l32irq1: B irqFirstLevelHandler
+
+ .balign 0x80
+l32fiq1: B fiqFirstLevelHandler
+
+ .balign 0x80
+l32serr1: B l32serr1
+
+//----------------------------------------------------------------
+
+ .section EL2VECTORS, "ax"
+ .align 11
+
+//
+// Current EL with SP0
+//
+el2_vectors:
+c0sync2: B c0sync2
+
+ .balign 0x80
+c0irq2: B irqFirstLevelHandler
+
+ .balign 0x80
+c0fiq2: B fiqFirstLevelHandler
+
+ .balign 0x80
+c0serr2: B c0serr2
+
+//
+// Current EL with SPx
+//
+ .balign 0x80
+cxsync2: B cxsync2
+
+ .balign 0x80
+cxirq2: B irqFirstLevelHandler
+
+ .balign 0x80
+cxfiq2: B fiqFirstLevelHandler
+
+ .balign 0x80
+cxserr2: B cxserr2
+
+//
+// Lower EL using AArch64
+//
+ .balign 0x80
+l64sync2: B l64sync2
+
+ .balign 0x80
+l64irq2: B irqFirstLevelHandler
+
+ .balign 0x80
+l64fiq2: B fiqFirstLevelHandler
+
+ .balign 0x80
+l64serr2: B l64serr2
+
+//
+// Lower EL using AArch32
+//
+ .balign 0x80
+l32sync2: B l32sync2
+
+ .balign 0x80
+l32irq2: B irqFirstLevelHandler
+
+ .balign 0x80
+l32fiq2: B fiqFirstLevelHandler
+
+ .balign 0x80
+l32serr2: B l32serr2
+
+//----------------------------------------------------------------
+
+ .section EL3VECTORS, "ax"
+ .align 11
+
+//
+// Current EL with SP0
+//
+el3_vectors:
+c0sync3: B c0sync3
+
+ .balign 0x80
+c0irq3: B irqFirstLevelHandler
+
+ .balign 0x80
+c0fiq3: B fiqFirstLevelHandler
+
+ .balign 0x80
+c0serr3: B c0serr3
+
+//
+// Current EL with SPx
+//
+ .balign 0x80
+cxsync3: B cxsync3
+
+ .balign 0x80
+cxirq3: B irqFirstLevelHandler
+
+ .balign 0x80
+cxfiq3: B fiqFirstLevelHandler
+
+ .balign 0x80
+cxserr3: B cxserr3
+
+//
+// Lower EL using AArch64
+//
+ .balign 0x80
+l64sync3: B l64sync3
+
+ .balign 0x80
+l64irq3: B irqFirstLevelHandler
+
+ .balign 0x80
+l64fiq3: B fiqFirstLevelHandler
+
+ .balign 0x80
+l64serr3: B l64serr3
+
+//
+// Lower EL using AArch32
+//
+ .balign 0x80
+l32sync3: B l32sync3
+
+ .balign 0x80
+l32irq3: B irqFirstLevelHandler
+
+ .balign 0x80
+l32fiq3: B fiqFirstLevelHandler
+
+ .balign 0x80
+l32serr3: B l32serr3
+
+
+ .section InterruptHandlers, "ax"
+ .balign 4
+
+ .type irqFirstLevelHandler, "function"
+irqFirstLevelHandler:
+ MSR SPSel, 0
+ STP x29, x30, [sp, #-16]!
+ BL _tx_thread_context_save
+ BL irqHandler
+ B _tx_thread_context_restore
+
+ .type fiqFirstLevelHandler, "function"
+fiqFirstLevelHandler:
+ STP x29, x30, [sp, #-16]!
+ STP x18, x19, [sp, #-16]!
+ STP x16, x17, [sp, #-16]!
+ STP x14, x15, [sp, #-16]!
+ STP x12, x13, [sp, #-16]!
+ STP x10, x11, [sp, #-16]!
+ STP x8, x9, [sp, #-16]!
+ STP x6, x7, [sp, #-16]!
+ STP x4, x5, [sp, #-16]!
+ STP x2, x3, [sp, #-16]!
+ STP x0, x1, [sp, #-16]!
+
+ BL fiqHandler
+
+ LDP x0, x1, [sp], #16
+ LDP x2, x3, [sp], #16
+ LDP x4, x5, [sp], #16
+ LDP x6, x7, [sp], #16
+ LDP x8, x9, [sp], #16
+ LDP x10, x11, [sp], #16
+ LDP x12, x13, [sp], #16
+ LDP x14, x15, [sp], #16
+ LDP x16, x17, [sp], #16
+ LDP x18, x19, [sp], #16
+ LDP x29, x30, [sp], #16
+ ERET
diff --git a/ports/cortex_a72/gnu/example_build/tx/.cproject b/ports/cortex_a72/gnu/example_build/tx/.cproject
new file mode 100644
index 00000000..01bcd509
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/tx/.cproject
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+
+ <cconfiguration id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915">
+
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+
+ <externalSettings/>
+
+ <extensions>
+
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ </extensions>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug.base">
+
+ <folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915." name="/" resourcePath="">
+
+ <toolChain id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.1652432530" name="GCC 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf">
+
+ <targetPlatform id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.1652432530.1250098983" name=""/>
+
+ <builder buildPath="${workspace_loc:/tx}/Debug" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder.408478790" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder"/>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1755052156" 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">
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu.281590127" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym.1254489229" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
+
+ <listOptionValue builtIn="false" value="STANDALONE"/>
+
+ <listOptionValue builtIn="false" value="ENABLE_ARM_FP"/>
+
+ </option>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath.1541383646" name="Include paths (-I)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath" useByScannerDiscovery="false" valueType="includePath">
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc_generic}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc_port}&quot;"/>
+
+ </option>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.379931340" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" value="gnu.c.optimization.level.none" valueType="enumerated"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input.11119542" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input"/>
+
+ </tool>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf.1308248336" name="GCC C++ Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf">
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.842447027" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" value="gnu.c.optimization.level.none" valueType="enumerated"/>
+
+ </tool>
+
+ <tool command="aarch64-elf-gcc.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf.2113642977" name="GCC Assembler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf">
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu.1603138513" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.defsym.1797095306" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
+
+ <listOptionValue builtIn="false" value="EL1"/>
+
+ </option>
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug.1075418381" name="Generate debugging information (-g)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input.93700751" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input"/>
+
+ </tool>
+
+ <tool command="aarch64-elf-ar.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf.1983468481" name="GCC C Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf">
+
+ <option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags.1806767239" name="Other flags" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags" useByScannerDiscovery="false" value="-r" valueType="string"/>
+
+ <inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input.1298708086" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input">
+
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+
+ </inputType>
+
+ <outputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.output.478221475" outputPrefix="lib" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.output"/>
+
+ </tool>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf.2101445430" name="GCC C++ Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf"/>
+
+ <tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf.1756490450" name="GCC Archiver 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf"/>
+
+ </toolChain>
+
+ </folderInfo>
+
+ <sourceEntries>
+
+ <entry excluding="src_generic/tx_misra.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+
+ </sourceEntries>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+
+ </cconfiguration>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <project id="tx.com.arm.eclipse.build.project.v6.lib.1209080418" name="Static Library"/>
+
+ </storageModule>
+
+ <storageModule moduleId="scannerConfiguration">
+
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+
+ <storageModule moduleId="refreshScope" versionNumber="2">
+
+ <configuration configurationName="Debug">
+
+ <resource resourceType="PROJECT" workspacePath="/tx"/>
+
+ </configuration>
+
+ <configuration configurationName="Release">
+
+ <resource resourceType="PROJECT" workspacePath="/tx"/>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+
+ <storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
+
+</cproject>
diff --git a/ports/cortex_a72/gnu/example_build/tx/.project b/ports/cortex_a72/gnu/example_build/tx/.project
new file mode 100644
index 00000000..863ca5cb
--- /dev/null
+++ b/ports/cortex_a72/gnu/example_build/tx/.project
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>tx</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>inc_generic</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI>
+ </link>
+ <link>
+ <name>inc_port</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI>
+ </link>
+ <link>
+ <name>src_generic</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/src</locationURI>
+ </link>
+ <link>
+ <name>src_port</name>
+ <type>2</type>
+ <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/src</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/ports/cortex_a72/gnu/inc/tx_port.h b/ports/cortex_a72/gnu/inc/tx_port.h
new file mode 100644
index 00000000..33bccbf1
--- /dev/null
+++ b/ports/cortex_a72/gnu/inc/tx_port.h
@@ -0,0 +1,379 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Port Specific */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* PORT SPECIFIC C INFORMATION RELEASE */
+/* */
+/* tx_port.h ARMv8-A */
+/* 6.1.10 */
+/* */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Bhupendra Naphade Modified comment(s),updated */
+/* macro definition, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/* Determine if the optional ThreadX user define file should be used. */
+
+#ifdef TX_INCLUDE_USER_DEFINE_FILE
+
+
+/* Yes, include the user defines in tx_user.h. The defines in this file may
+ alternately be defined on the command line. */
+
+#include "tx_user.h"
+#endif
+
+
+/* Define compiler library include files. */
+
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Define ThreadX basic types for this port. */
+
+#define VOID void
+typedef char CHAR;
+typedef unsigned char UCHAR;
+typedef int INT;
+typedef unsigned int UINT;
+typedef int LONG;
+typedef unsigned int ULONG;
+typedef unsigned long long ULONG64;
+typedef short SHORT;
+typedef unsigned short USHORT;
+#define ULONG64_DEFINED
+
+/* Override the alignment type to use 64-bit alignment and storage for pointers. */
+
+#define ALIGN_TYPE_DEFINED
+typedef unsigned long long ALIGN_TYPE;
+
+
+/* Override the free block marker for byte pools to be a 64-bit constant. */
+
+#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE)
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 4096 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX ARM port. */
+
+#define TX_INT_DISABLE 0xC0 /* Disable 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.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_MISRA_ENABLE
+#ifndef TX_TRACE_TIME_SOURCE
+#define TX_TRACE_TIME_SOURCE _tx_thread_smp_time_get()
+#endif
+#else
+#ifndef TX_TRACE_TIME_SOURCE
+ULONG _tx_misra_time_stamp_get(VOID);
+#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
+#endif
+#endif
+#ifndef TX_TRACE_TIME_MASK
+#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
+#endif
+
+
+/* Define the port specific options for the _tx_build_options variable. This variable indicates
+ how the ThreadX library was built. */
+
+#ifdef TX_ENABLE_FIQ_SUPPORT
+#define TX_FIQ_ENABLED 1
+#else
+#define TX_FIQ_ENABLED 0
+#endif
+
+#ifdef TX_ENABLE_IRQ_NESTING
+#define TX_IRQ_NESTING_ENABLED 2
+#else
+#define TX_IRQ_NESTING_ENABLED 0
+#endif
+
+#ifdef TX_ENABLE_FIQ_NESTING
+#define TX_FIQ_NESTING_ENABLED 4
+#else
+#define TX_FIQ_NESTING_ENABLED 0
+#endif
+
+#define TX_PORT_SPECIFIC_BUILD_OPTIONS (TX_FIQ_ENABLED | TX_IRQ_NESTING_ENABLED | TX_FIQ_NESTING_ENABLED)
+
+
+/* Define the in-line initialization constant so that modules with in-line
+ initialization capabilities can prevent their initialization from being
+ a function call. */
+
+#ifdef TX_MISRA_ENABLE
+#define TX_DISABLE_INLINE
+#else
+#define TX_INLINE_INITIALIZATION
+#endif
+
+
+/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
+ disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
+ checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
+ define is negated, thereby forcing the stack fill which is necessary for the stack checking
+ logic. */
+
+#ifndef TX_MISRA_ENABLE
+#ifdef TX_ENABLE_STACK_CHECKING
+#undef TX_DISABLE_STACK_FILLING
+#endif
+#endif
+
+
+/* Define the TX_THREAD control block extensions for this port. The main reason
+ for the multiple macros is so that backward compatibility can be maintained with
+ existing ThreadX kernel awareness modules. */
+
+#define TX_THREAD_EXTENSION_0
+#define TX_THREAD_EXTENSION_1
+#define TX_THREAD_EXTENSION_2 ULONG tx_thread_fp_enable;
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
+#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
+
+
+/* Define the ThreadX object deletion extensions for the remaining objects. */
+
+#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
+#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
+#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
+#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
+#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
+#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
+
+
+/* Determine if the ARM architecture has the CLZ instruction. This is available on
+ architectures v5 and above. If available, redefine the macro for calculating the
+ lowest bit set. */
+
+#ifndef TX_DISABLE_INLINE
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) b = (UINT) __builtin_ctz((unsigned int) m);
+
+#endif
+
+
+/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout
+ can figure out what thread timeout to process. */
+
+#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_thread_timeout_ptr;
+
+
+/* Define the thread timeout setup logic in _tx_thread_create. */
+
+#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
+ (t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \
+ (t) -> tx_thread_timer.tx_timer_internal_thread_timeout_ptr = (VOID *) (t);
+
+
+/* Define the thread timeout pointer setup in _tx_thread_timeout. */
+
+#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_thread_timeout_ptr;
+
+
+/* Define ThreadX interrupt lockout and restore macros for protection on
+ access of critical kernel information. The restore interrupt macro must
+ restore the interrupt posture of the running thread prior to the value
+ present prior to the disable macro. In most cases, the save area macro
+ is used to define a local function save area for the disable and restore
+ macros. */
+
+#ifndef TX_DISABLE_INLINE
+
+/* Define macros, with in-line assembly for performance. */
+
+__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
+{
+
+unsigned long long daif_value;
+
+ __asm__ volatile (" MRS %0, DAIF ": "=r" (daif_value) );
+ __asm__ volatile (" MSR DAIFSet, 0x3" : : : "memory" );
+ return((unsigned int) daif_value);
+}
+
+__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int daif_value)
+{
+
+unsigned long long temp;
+
+ temp = (unsigned long long) daif_value;
+ __asm__ volatile (" MSR DAIF,%0": : "r" (temp): "memory" );
+}
+
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+#define TX_DISABLE interrupt_save = __disable_interrupts();
+#define TX_RESTORE __restore_interrupts(interrupt_save);
+
+#else
+
+unsigned int _tx_thread_interrupt_disable(void);
+unsigned int _tx_thread_interrupt_restore(UINT old_posture);
+
+
+#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
+#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
+#endif
+
+
+/* Define the interrupt lockout macros for each ThreadX object. */
+
+#define TX_BLOCK_POOL_DISABLE TX_DISABLE
+#define TX_BYTE_POOL_DISABLE TX_DISABLE
+#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
+#define TX_MUTEX_DISABLE TX_DISABLE
+#define TX_QUEUE_DISABLE TX_DISABLE
+#define TX_SEMAPHORE_DISABLE TX_DISABLE
+
+
+/* Define FP extension for ARMv8. Each is assumed to be called in the context of the executing thread. */
+
+#ifndef TX_SOURCE_CODE
+#define tx_thread_fp_enable _tx_thread_fp_enable
+#define tx_thread_fp_disable _tx_thread_fp_disable
+#endif
+
+VOID tx_thread_fp_enable(VOID);
+VOID tx_thread_fp_disable(VOID);
+
+
+/* Define the version ID of ThreadX. This may be utilized by the application. */
+
+#ifdef TX_THREAD_INIT
+CHAR _tx_version_id[] =
+ "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX ARMv8-A Version 6.1.10 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
diff --git a/ports/cortex_a72/gnu/src/tx_initialize_low_level.S b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S
new file mode 100644
index 00000000..bf04784e
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S
@@ -0,0 +1,98 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Initialize */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for any low-level processor */
+/* initialization, including setting up interrupt vectors, setting */
+/* up a periodic timer interrupt source, saving the system stack */
+/* pointer for use in ISR processing later, and finding the first */
+/* available RAM memory address for tx_application_define. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ .global _tx_initialize_low_level
+ .type _tx_initialize_low_level, @function
+_tx_initialize_low_level:
+
+ MSR DAIFSet, 0x3 // Lockout interrupts
+
+
+ /* Save the system stack pointer. */
+ // _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
+
+ LDR x0, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr
+ MOV x1, sp // Pickup SP
+ SUB x1, x1, #15 //
+ BIC x1, x1, #0xF // Get 16-bit alignment
+ STR x1, [x0] // Store system stack
+
+ /* Save the first available memory address. */
+ // _tx_initialize_unused_memory = (VOID_PTR) Image$$ZI$$Limit;
+
+ LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr
+ LDR x1, =__top_of_ram // Pickup unused memory address
+ LDR x1, [x1] //
+ STR x1, [x0] // Store unused memory address
+
+ /* Done, return to caller. */
+
+ RET // Return to caller
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_context_restore.S b/ports/cortex_a72/gnu/src/tx_thread_context_restore.S
new file mode 100644
index 00000000..994c404d
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_context_restore.S
@@ -0,0 +1,287 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function restores the interrupt context if it is processing a */
+/* nested interrupt. If not, it returns to the interrupt thread if no */
+/* preemption is necessary. Otherwise, if preemption is necessary or */
+/* if no thread was running, the function returns to the scheduler. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_schedule Thread scheduling routine */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs Interrupt Service Routines */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ .global _tx_thread_context_restore
+ .type _tx_thread_context_restore, @function
+_tx_thread_context_restore:
+
+ /* Lockout interrupts. */
+
+ MSR DAIFSet, 0x3 // Lockout interrupts
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+
+ /* Call the ISR exit function to indicate an ISR is complete. */
+
+ BL _tx_execution_isr_exit // Call the ISR exit function
+#endif
+
+ /* Determine if interrupts are nested. */
+ // if (--_tx_thread_system_state)
+ // {
+
+ LDR x3, =_tx_thread_system_state // Pickup address of system state var
+ LDR w2, [x3, #0] // Pickup system state
+ SUB w2, w2, #1 // Decrement the counter
+ STR w2, [x3, #0] // Store the counter
+ CMP w2, #0 // Was this the first interrupt?
+ BEQ __tx_thread_not_nested_restore // If so, not a nested restore
+
+ /* Interrupts are nested. */
+
+ /* Just recover the saved registers and return to the point of
+ interrupt. */
+
+ LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL
+#ifdef EL1
+ MSR SPSR_EL1, x4 // Setup SPSR for return
+ MSR ELR_EL1, x5 // Setup point of interrupt
+#else
+#ifdef EL2
+ MSR SPSR_EL2, x4 // Setup SPSR for return
+ MSR ELR_EL2, x5 // Setup point of interrupt
+#else
+ MSR SPSR_EL3, x4 // Setup SPSR for return
+ MSR ELR_EL3, x5 // Setup point of interrupt
+#endif
+#endif
+ LDP x18, x19, [sp], #16 // Recover x18, x19
+ LDP x16, x17, [sp], #16 // Recover x16, x17
+ LDP x14, x15, [sp], #16 // Recover x14, x15
+ LDP x12, x13, [sp], #16 // Recover x12, x13
+ LDP x10, x11, [sp], #16 // Recover x10, x11
+ LDP x8, x9, [sp], #16 // Recover x8, x9
+ LDP x6, x7, [sp], #16 // Recover x6, x7
+ LDP x4, x5, [sp], #16 // Recover x4, x5
+ LDP x2, x3, [sp], #16 // Recover x2, x3
+ LDP x0, x1, [sp], #16 // Recover x0, x1
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+ ERET // Return to point of interrupt
+
+ // }
+__tx_thread_not_nested_restore:
+
+ /* Determine if a thread was interrupted and no preemption is required. */
+ // else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
+ // || (_tx_thread_preempt_disable))
+ // {
+
+ LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ LDR x0, [x1, #0] // Pickup actual current thread pointer
+ CMP x0, #0 // Is it NULL?
+ BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted
+
+ LDR x3, =_tx_thread_preempt_disable // Pickup preempt disable address
+ LDR w2, [x3, #0] // Pickup actual preempt disable flag
+ CMP w2, #0 // Is it set?
+ BNE __tx_thread_no_preempt_restore // Yes, don't preempt this thread
+ LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
+ LDR x2, [x3, #0] // Pickup actual execute thread pointer
+ CMP x0, x2 // Is the same thread highest priority?
+ BNE __tx_thread_preempt_restore // No, preemption needs to happen
+
+
+__tx_thread_no_preempt_restore:
+
+ /* Restore interrupted thread or ISR. */
+
+ /* Pickup the saved stack pointer. */
+ // sp = _tx_thread_current_ptr -> tx_thread_stack_ptr;
+
+ LDR x4, [x0, #8] // Switch to thread stack pointer
+ MOV sp, x4 //
+
+ /* Recover the saved context and return to the point of interrupt. */
+
+ LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
+#ifdef EL1
+ MSR SPSR_EL1, x4 // Setup SPSR for return
+ MSR ELR_EL1, x5 // Setup point of interrupt
+#else
+#ifdef EL2
+ MSR SPSR_EL2, x4 // Setup SPSR for return
+ MSR ELR_EL2, x5 // Setup point of interrupt
+#else
+ MSR SPSR_EL3, x4 // Setup SPSR for return
+ MSR ELR_EL3, x5 // Setup point of interrupt
+#endif
+#endif
+ LDP x18, x19, [sp], #16 // Recover x18, x19
+ LDP x16, x17, [sp], #16 // Recover x16, x17
+ LDP x14, x15, [sp], #16 // Recover x14, x15
+ LDP x12, x13, [sp], #16 // Recover x12, x13
+ LDP x10, x11, [sp], #16 // Recover x10, x11
+ LDP x8, x9, [sp], #16 // Recover x8, x9
+ LDP x6, x7, [sp], #16 // Recover x6, x7
+ LDP x4, x5, [sp], #16 // Recover x4, x5
+ LDP x2, x3, [sp], #16 // Recover x2, x3
+ LDP x0, x1, [sp], #16 // Recover x0, x1
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+ ERET // Return to point of interrupt
+
+ // }
+ // else
+ // {
+__tx_thread_preempt_restore:
+
+ LDR x4, [x0, #8] // Switch to thread stack pointer
+ MOV sp, x4 //
+
+ LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
+ STP x20, x21, [sp, #-16]! // Save x20, x21
+ STP x22, x23, [sp, #-16]! // Save x22, x23
+ STP x24, x25, [sp, #-16]! // Save x24, x25
+ STP x26, x27, [sp, #-16]! // Save x26, x27
+ STP x28, x29, [sp, #-16]! // Save x28, x29
+#ifdef ENABLE_ARM_FP
+ LDR w3, [x0, #248] // Pickup FP enable flag
+ CMP w3, #0 // Is FP enabled?
+ BEQ _skip_fp_save // No, skip FP save
+ STP q0, q1, [sp, #-32]! // Save q0, q1
+ STP q2, q3, [sp, #-32]! // Save q2, q3
+ STP q4, q5, [sp, #-32]! // Save q4, q5
+ STP q6, q7, [sp, #-32]! // Save q6, q7
+ STP q8, q9, [sp, #-32]! // Save q8, q9
+ STP q10, q11, [sp, #-32]! // Save q10, q11
+ STP q12, q13, [sp, #-32]! // Save q12, q13
+ STP q14, q15, [sp, #-32]! // Save q14, q15
+ STP q16, q17, [sp, #-32]! // Save q16, q17
+ STP q18, q19, [sp, #-32]! // Save q18, q19
+ STP q20, q21, [sp, #-32]! // Save q20, q21
+ STP q22, q23, [sp, #-32]! // Save q22, q23
+ STP q24, q25, [sp, #-32]! // Save q24, q25
+ STP q26, q27, [sp, #-32]! // Save q26, q27
+ STP q28, q29, [sp, #-32]! // Save q28, q29
+ STP q30, q31, [sp, #-32]! // Save q30, q31
+ MRS x2, FPSR // Pickup FPSR
+ MRS x3, FPCR // Pickup FPCR
+ STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
+_skip_fp_save:
+#endif
+ STP x4, x5, [sp, #-16]! // Save x4 (SPSR_EL3), x5 (ELR_E3)
+
+ MOV x3, sp // Move sp into x3
+ STR x3, [x0, #8] // Save stack pointer in thread control
+ // block
+ LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
+ LDR x4, [x3, #0] // Pickup system stack pointer
+ MOV sp, x4 // Setup system stack pointer
+
+
+ /* Save the remaining time-slice and disable it. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ LDR x3, =_tx_timer_time_slice // Pickup time-slice variable address
+ LDR w2, [x3, #0] // Pickup time-slice
+ CMP w2, #0 // Is it active?
+ BEQ __tx_thread_dont_save_ts // No, don't save it
+
+ // _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
+ // _tx_timer_time_slice = 0;
+
+ STR w2, [x0, #36] // Save thread's time-slice
+ MOV w2, #0 // Clear value
+ STR w2, [x3, #0] // Disable global time-slice flag
+
+ // }
+__tx_thread_dont_save_ts:
+
+
+ /* Clear the current task pointer. */
+ /* _tx_thread_current_ptr = TX_NULL; */
+
+ MOV x0, #0 // NULL value
+ STR x0, [x1, #0] // Clear current thread pointer
+
+ /* Return to the scheduler. */
+ // _tx_thread_schedule();
+
+ // }
+
+__tx_thread_idle_system_restore:
+
+ /* Just return back to the scheduler! */
+
+ LDR x1, =_tx_thread_schedule // Build address for _tx_thread_schedule
+#ifdef EL1
+ MSR ELR_EL1, x1 // Setup point of interrupt
+// MOV x1, #0x4 // Setup EL1 return
+// MSR spsr_el1, x1 // Move into SPSR
+#else
+#ifdef EL2
+ MSR ELR_EL2, x1 // Setup point of interrupt
+// MOV x1, #0x8 // Setup EL2 return
+// MSR spsr_el2, x1 // Move into SPSR
+#else
+ MSR ELR_EL3, x1 // Setup point of interrupt
+// MOV x1, #0xC // Setup EL3 return
+// MSR spsr_el3, x1 // Move into SPSR
+#endif
+#endif
+ ERET // Return to scheduler
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_context_save.S b/ports/cortex_a72/gnu/src/tx_thread_context_save.S
new file mode 100644
index 00000000..859a1e44
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_context_save.S
@@ -0,0 +1,216 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves the context of an executing thread in the */
+/* beginning of interrupt processing. The function also ensures that */
+/* the system stack is used upon return to the calling ISR. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ .global _tx_thread_context_save
+ .type _tx_thread_context_save, @function
+_tx_thread_context_save:
+
+ /* Upon entry to this routine, it is assumed that IRQ/FIQ interrupts are locked
+ out, x29 (frame pointer), x30 (link register) are saved, we are in EL1,
+ and all other registers are intact. */
+
+ /* Check for a nested interrupt condition. */
+ // if (_tx_thread_system_state++)
+ // {
+
+ STP x0, x1, [sp, #-16]! // Save x0, x1
+ STP x2, x3, [sp, #-16]! // Save x2, x3
+ LDR x3, =_tx_thread_system_state // Pickup address of system state var
+ LDR w2, [x3, #0] // Pickup system state
+ CMP w2, #0 // Is this the first interrupt?
+ BEQ __tx_thread_not_nested_save // Yes, not a nested context save
+
+ /* Nested interrupt condition. */
+
+ ADD w2, w2, #1 // Increment the nested interrupt counter
+ STR w2, [x3, #0] // Store it back in the variable
+
+ /* Save the rest of the scratch registers on the stack and return to the
+ calling ISR. */
+
+ STP x4, x5, [sp, #-16]! // Save x4, x5
+ STP x6, x7, [sp, #-16]! // Save x6, x7
+ STP x8, x9, [sp, #-16]! // Save x8, x9
+ STP x10, x11, [sp, #-16]! // Save x10, x11
+ STP x12, x13, [sp, #-16]! // Save x12, x13
+ STP x14, x15, [sp, #-16]! // Save x14, x15
+ STP x16, x17, [sp, #-16]! // Save x16, x17
+ STP x18, x19, [sp, #-16]! // Save x18, x19
+#ifdef EL1
+ MRS x0, SPSR_EL1 // Pickup SPSR
+ MRS x1, ELR_EL1 // Pickup ELR (point of interrupt)
+#else
+#ifdef EL2
+ MRS x0, SPSR_EL2 // Pickup SPSR
+ MRS x1, ELR_EL2 // Pickup ELR (point of interrupt)
+#else
+ MRS x0, SPSR_EL3 // Pickup SPSR
+ MRS x1, ELR_EL3 // Pickup ELR (point of interrupt)
+#endif
+#endif
+ STP x0, x1, [sp, #-16]! // Save SPSR, ELR
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ STP x29, x30, [sp, #-16]! // Save x29, x30
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+#endif
+
+ /* Return to the ISR. */
+
+ RET // Return to ISR
+
+__tx_thread_not_nested_save:
+ // }
+
+ /* Otherwise, not nested, check to see if a thread was running. */
+ // else if (_tx_thread_current_ptr)
+ // {
+
+ ADD w2, w2, #1 // Increment the interrupt counter
+ STR w2, [x3, #0] // Store it back in the variable
+ LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ LDR x0, [x1, #0] // Pickup current thread pointer
+ CMP x0, #0 // Is it NULL?
+ BEQ __tx_thread_idle_system_save // If so, interrupt occurred in
+ // scheduling loop - nothing needs saving!
+
+ /* Save minimal context of interrupted thread. */
+
+ STP x4, x5, [sp, #-16]! // Save x4, x5
+ STP x6, x7, [sp, #-16]! // Save x6, x7
+ STP x8, x9, [sp, #-16]! // Save x8, x9
+ STP x10, x11, [sp, #-16]! // Save x10, x11
+ STP x12, x13, [sp, #-16]! // Save x12, x13
+ STP x14, x15, [sp, #-16]! // Save x14, x15
+ STP x16, x17, [sp, #-16]! // Save x16, x17
+ STP x18, x19, [sp, #-16]! // Save x18, x19
+#ifdef EL1
+ MRS x4, SPSR_EL1 // Pickup SPSR
+ MRS x5, ELR_EL1 // Pickup ELR (point of interrupt)
+#else
+#ifdef EL2
+ MRS x4, SPSR_EL2 // Pickup SPSR
+ MRS x5, ELR_EL2 // Pickup ELR (point of interrupt)
+#else
+ MRS x4, SPSR_EL3 // Pickup SPSR
+ MRS x5, ELR_EL3 // Pickup ELR (point of interrupt)
+#endif
+#endif
+ STP x4, x5, [sp, #-16]! // Save SPSR, ELR
+
+ /* Save the current stack pointer in the thread's control block. */
+ // _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
+
+ MOV x4, sp //
+ STR x4, [x0, #8] // Save thread stack pointer
+
+ /* Switch to the system stack. */
+ // sp = _tx_thread_system_stack_ptr;
+
+ LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
+ LDR x4, [x3, #0] // Pickup system stack pointer
+ MOV sp, x4 // Setup system stack pointer
+
+#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ STP x29, x30, [sp, #-16]! // Save x29, x30
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+#endif
+
+ RET // Return to caller
+
+ // }
+ // else
+ // {
+
+__tx_thread_idle_system_save:
+
+ /* Interrupt occurred in the scheduling loop. */
+
+ /* Not much to do here, just adjust the stack pointer, and return to IRQ
+ processing. */
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ STP x29, x30, [sp, #-16]! // Save x29, x30
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+#endif
+
+ ADD sp, sp, #48 // Recover saved registers
+ RET // Continue IRQ processing
+
+ // }
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_fp_disable.c b/ports/cortex_a72/gnu/src/tx_thread_fp_disable.c
new file mode 100644
index 00000000..3e5d7e21
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_fp_disable.c
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_fp_disable ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function disables the FP for the currently executing thread. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_fp_disable(VOID)
+{
+
+TX_THREAD *thread_ptr;
+ULONG system_state;
+
+
+ /* Pickup the current thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr);
+
+ /* Get the system state. */
+ system_state = TX_THREAD_GET_SYSTEM_STATE();
+
+ /* Make sure it is not NULL. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Thread is running... make sure the call is from the thread context. */
+ if (system_state == 0)
+ {
+
+ /* Yes, now set the FP enable flag to false in the TX_THREAD structure. */
+ thread_ptr -> tx_thread_fp_enable = TX_FALSE;
+ }
+ }
+}
+
diff --git a/ports/cortex_a72/gnu/src/tx_thread_fp_enable.c b/ports/cortex_a72/gnu/src/tx_thread_fp_enable.c
new file mode 100644
index 00000000..4e69205c
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_fp_enable.c
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files. */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_fp_enable ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function enabled the FP for the currently executing thread. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+VOID _tx_thread_fp_enable(VOID)
+{
+
+TX_THREAD *thread_ptr;
+ULONG system_state;
+
+
+ /* Pickup the current thread pointer. */
+ TX_THREAD_GET_CURRENT(thread_ptr);
+
+ /* Get the system state. */
+ system_state = TX_THREAD_GET_SYSTEM_STATE();
+
+ /* Make sure it is not NULL. */
+ if (thread_ptr != TX_NULL)
+ {
+
+ /* Thread is running... make sure the call is from the thread context. */
+ if (system_state == 0)
+ {
+
+ /* Yes, now setup the FP enable flag in the TX_THREAD structure. */
+ thread_ptr -> tx_thread_fp_enable = TX_TRUE;
+ }
+ }
+}
+
diff --git a/ports/cortex_a72/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_a72/gnu/src/tx_thread_interrupt_control.S
new file mode 100644
index 00000000..6a5a7741
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_interrupt_control.S
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for changing the interrupt lockout */
+/* posture of the system. */
+/* */
+/* INPUT */
+/* */
+/* new_posture New interrupt lockout posture */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ .global _tx_thread_interrupt_control
+ .type _tx_thread_interrupt_control, @function
+_tx_thread_interrupt_control:
+
+ /* Pickup current interrupt lockout posture. */
+
+ MRS x1, DAIF // Pickup current interrupt posture
+
+ /* Apply the new interrupt posture. */
+
+ MSR DAIF, x0 // Set new interrupt posture
+ MOV x0, x1 // Setup return value
+ RET // Return to caller
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_a72/gnu/src/tx_thread_interrupt_disable.S
new file mode 100644
index 00000000..d0062ef8
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_interrupt_disable.S
@@ -0,0 +1,79 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for disabling interrupts */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(void)
+// {
+ .global _tx_thread_interrupt_disable
+ .type _tx_thread_interrupt_disable, @function
+_tx_thread_interrupt_disable:
+
+ /* Pickup current interrupt lockout posture. */
+
+ MRS x0, DAIF // Pickup current interrupt lockout posture
+
+ /* Mask interrupts. */
+
+ MSR DAIFSet, 0x3 // Lockout interrupts
+ RET // Return to caller
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_a72/gnu/src/tx_thread_interrupt_restore.S
new file mode 100644
index 00000000..1b6261ba
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_interrupt_restore.S
@@ -0,0 +1,77 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for restoring interrupts to the state */
+/* returned by a previous _tx_thread_interrupt_disable call. */
+/* */
+/* INPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_restore(UINT old_posture)
+// {
+ .global _tx_thread_interrupt_restore
+ .type _tx_thread_interrupt_restore, @function
+_tx_thread_interrupt_restore:
+
+ /* Restore the old interrupt posture. */
+
+ MSR DAIF, x0 // Setup the old posture
+ RET // Return to caller
+
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_schedule.S b/ports/cortex_a72/gnu/src/tx_thread_schedule.S
new file mode 100644
index 00000000..9a7a7262
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_schedule.S
@@ -0,0 +1,228 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function waits for a thread control block pointer to appear in */
+/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+/* in the variable, the corresponding thread is resumed. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* _tx_thread_system_return Return to system from thread */
+/* _tx_thread_context_restore Restore thread's context */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* added ARMv8.2-A support, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ .global _tx_thread_schedule
+ .type _tx_thread_schedule, @function
+_tx_thread_schedule:
+
+ /* Enable interrupts. */
+
+ MSR DAIFClr, 0x3 // Enable interrupts
+
+ /* Wait for a thread to execute. */
+ // do
+ // {
+
+ LDR x1, =_tx_thread_execute_ptr // Address of thread execute ptr
+
+#ifdef TX_ENABLE_WFI
+__tx_thread_schedule_loop:
+ LDR x0, [x1, #0] // Pickup next thread to execute
+ CMP x0, #0 // Is it NULL?
+ BNE _tx_thread_schedule_thread //
+ WFI //
+ B __tx_thread_schedule_loop // Keep looking for a thread
+_tx_thread_schedule_thread:
+#else
+__tx_thread_schedule_loop:
+ LDR x0, [x1, #0] // Pickup next thread to execute
+ CMP x0, #0 // Is it NULL?
+ BEQ __tx_thread_schedule_loop // If so, keep looking for a thread
+#endif
+
+ // }
+ // while(_tx_thread_execute_ptr == TX_NULL);
+
+ /* Yes! We have a thread to execute. Lockout interrupts and
+ transfer control to it. */
+
+ MSR DAIFSet, 0x3 // Lockout interrupts
+
+ /* Setup the current thread pointer. */
+ // _tx_thread_current_ptr = _tx_thread_execute_ptr;
+
+ LDR x1, =_tx_thread_current_ptr // Pickup address of current thread
+ STR x0, [x1, #0] // Setup current thread pointer
+
+ /* Increment the run count for this thread. */
+ // _tx_thread_current_ptr -> tx_thread_run_count++;
+
+ LDR w2, [x0, #4] // Pickup run counter
+ LDR w3, [x0, #36] // Pickup time-slice for this thread
+ ADD w2, w2, #1 // Increment thread run-counter
+ STR w2, [x0, #4] // Store the new run counter
+
+ /* Setup time-slice, if present. */
+ // _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
+
+ LDR x2, =_tx_timer_time_slice // Pickup address of time slice
+ // variable
+ LDR x4, [x0, #8] // Switch stack pointers
+ MOV sp, x4 //
+ STR w3, [x2, #0] // Setup time-slice
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+
+ /* Call the thread entry function to indicate the thread is executing. */
+
+ MOV x19, x0 // Save x0
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ MOV x0, x19 // Restore x0
+#endif
+
+ /* Switch to the thread's stack. */
+ // sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr;
+
+ /* Determine if an interrupt frame or a synchronous task suspension frame
+ is present. */
+
+ LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
+ CMP x5, #0 // Check for synchronous context switch (ELR_EL1 = NULL)
+ BEQ _tx_solicited_return
+#ifdef EL1
+ MSR SPSR_EL1, x4 // Setup SPSR for return
+ MSR ELR_EL1, x5 // Setup point of interrupt
+#else
+#ifdef EL2
+ MSR SPSR_EL2, x4 // Setup SPSR for return
+ MSR ELR_EL2, x5 // Setup point of interrupt
+#else
+ MSR SPSR_EL3, x4 // Setup SPSR for return
+ MSR ELR_EL3, x5 // Setup point of interrupt
+#endif
+#endif
+#ifdef ENABLE_ARM_FP
+ LDR w1, [x0, #248] // Pickup FP enable flag
+ CMP w1, #0 // Is FP enabled?
+ BEQ _skip_interrupt_fp_restore // No, skip FP restore
+ LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
+ MSR FPSR, x0 // Recover FPSR
+ MSR FPCR, x1 // Recover FPCR
+ LDP q30, q31, [sp], #32 // Recover q30, q31
+ LDP q28, q29, [sp], #32 // Recover q28, q29
+ LDP q26, q27, [sp], #32 // Recover q26, q27
+ LDP q24, q25, [sp], #32 // Recover q24, q25
+ LDP q22, q23, [sp], #32 // Recover q22, q23
+ LDP q20, q21, [sp], #32 // Recover q20, q21
+ LDP q18, q19, [sp], #32 // Recover q18, q19
+ LDP q16, q17, [sp], #32 // Recover q16, q17
+ LDP q14, q15, [sp], #32 // Recover q14, q15
+ LDP q12, q13, [sp], #32 // Recover q12, q13
+ LDP q10, q11, [sp], #32 // Recover q10, q11
+ LDP q8, q9, [sp], #32 // Recover q8, q9
+ LDP q6, q7, [sp], #32 // Recover q6, q7
+ LDP q4, q5, [sp], #32 // Recover q4, q5
+ LDP q2, q3, [sp], #32 // Recover q2, q3
+ LDP q0, q1, [sp], #32 // Recover q0, q1
+_skip_interrupt_fp_restore:
+#endif
+ LDP x28, x29, [sp], #16 // Recover x28
+ LDP x26, x27, [sp], #16 // Recover x26, x27
+ LDP x24, x25, [sp], #16 // Recover x24, x25
+ LDP x22, x23, [sp], #16 // Recover x22, x23
+ LDP x20, x21, [sp], #16 // Recover x20, x21
+ LDP x18, x19, [sp], #16 // Recover x18, x19
+ LDP x16, x17, [sp], #16 // Recover x16, x17
+ LDP x14, x15, [sp], #16 // Recover x14, x15
+ LDP x12, x13, [sp], #16 // Recover x12, x13
+ LDP x10, x11, [sp], #16 // Recover x10, x11
+ LDP x8, x9, [sp], #16 // Recover x8, x9
+ LDP x6, x7, [sp], #16 // Recover x6, x7
+ LDP x4, x5, [sp], #16 // Recover x4, x5
+ LDP x2, x3, [sp], #16 // Recover x2, x3
+ LDP x0, x1, [sp], #16 // Recover x0, x1
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+ ERET // Return to point of interrupt
+
+_tx_solicited_return:
+
+#ifdef ENABLE_ARM_FP
+ LDR w1, [x0, #248] // Pickup FP enable flag
+ CMP w1, #0 // Is FP enabled?
+ BEQ _skip_solicited_fp_restore // No, skip FP restore
+ LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
+ MSR FPSR, x0 // Recover FPSR
+ MSR FPCR, x1 // Recover FPCR
+ LDP q14, q15, [sp], #32 // Recover q14, q15
+ LDP q12, q13, [sp], #32 // Recover q12, q13
+ LDP q10, q11, [sp], #32 // Recover q10, q11
+ LDP q8, q9, [sp], #32 // Recover q8, q9
+_skip_solicited_fp_restore:
+#endif
+ LDP x27, x28, [sp], #16 // Recover x27, x28
+ LDP x25, x26, [sp], #16 // Recover x25, x26
+ LDP x23, x24, [sp], #16 // Recover x23, x24
+ LDP x21, x22, [sp], #16 // Recover x21, x22
+ LDP x19, x20, [sp], #16 // Recover x19, x20
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+ MSR DAIF, x4 // Recover DAIF
+ RET // Return to caller
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_stack_build.S b/ports/cortex_a72/gnu/src/tx_thread_stack_build.S
new file mode 100644
index 00000000..5b7e945a
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_stack_build.S
@@ -0,0 +1,158 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function builds a stack frame on the supplied thread's stack. */
+/* The stack frame results in a fake interrupt return to the supplied */
+/* function pointer. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread */
+/* function_ptr Pointer to entry function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 01-31-2022 Andres Mlinar Updated comments, */
+/* resulting in version 6.1.10 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ .global _tx_thread_stack_build
+ .type _tx_thread_stack_build, @function
+_tx_thread_stack_build:
+
+
+ /* Build an interrupt frame. On Cortex-A35 it should look like this:
+
+ Stack Top: SSPR Initial SSPR
+ ELR Point of interrupt
+ x28 Initial value for x28
+ not used Not used
+ x26 Initial value for x26
+ x27 Initial value for x27
+ x24 Initial value for x24
+ x25 Initial value for x25
+ x22 Initial value for x22
+ x23 Initial value for x23
+ x20 Initial value for x20
+ x21 Initial value for x21
+ x18 Initial value for x18
+ x19 Initial value for x19
+ x16 Initial value for x16
+ x17 Initial value for x17
+ x14 Initial value for x14
+ x15 Initial value for x15
+ x12 Initial value for x12
+ x13 Initial value for x13
+ x10 Initial value for x10
+ x11 Initial value for x11
+ x8 Initial value for x8
+ x9 Initial value for x9
+ x6 Initial value for x6
+ x7 Initial value for x7
+ x4 Initial value for x4
+ x5 Initial value for x5
+ x2 Initial value for x2
+ x3 Initial value for x3
+ x0 Initial value for x0
+ x1 Initial value for x1
+ x29 Initial value for x29 (frame pointer)
+ x30 Initial value for x30 (link register)
+ 0 For stack backtracing
+
+ Stack Bottom: (higher memory address) */
+
+ LDR x4, [x0, #24] // Pickup end of stack area
+ BIC x4, x4, #0xF // Ensure 16-byte alignment
+
+ /* Actually build the stack frame. */
+
+ MOV x2, #0 // Build clear value
+ MOV x3, #0 //
+
+ STP x2, x3, [x4, #-16]! // Set backtrace to 0
+ STP x2, x3, [x4, #-16]! // Set initial x29, x30
+ STP x2, x3, [x4, #-16]! // Set initial x0, x1
+ STP x2, x3, [x4, #-16]! // Set initial x2, x3
+ STP x2, x3, [x4, #-16]! // Set initial x4, x5
+ STP x2, x3, [x4, #-16]! // Set initial x6, x7
+ STP x2, x3, [x4, #-16]! // Set initial x8, x9
+ STP x2, x3, [x4, #-16]! // Set initial x10, x11
+ STP x2, x3, [x4, #-16]! // Set initial x12, x13
+ STP x2, x3, [x4, #-16]! // Set initial x14, x15
+ STP x2, x3, [x4, #-16]! // Set initial x16, x17
+ STP x2, x3, [x4, #-16]! // Set initial x18, x19
+ STP x2, x3, [x4, #-16]! // Set initial x20, x21
+ STP x2, x3, [x4, #-16]! // Set initial x22, x23
+ STP x2, x3, [x4, #-16]! // Set initial x24, x25
+ STP x2, x3, [x4, #-16]! // Set initial x26, x27
+ STP x2, x3, [x4, #-16]! // Set initial x28
+#ifdef EL1
+ MOV x2, #0x4 // Build initial SPSR (EL1)
+#else
+#ifdef EL2
+ MOV x2, #0x8 // Build initial SPSR (EL2)
+#else
+ MOV x2, #0xC // Build initial SPSR (EL3)
+#endif
+#endif
+ MOV x3, x1 // Build initial ELR
+ STP x2, x3, [x4, #-16]! // Set initial SPSR & ELR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = x2;
+
+ STR x4, [x0, #8] // Save stack pointer in thread's
+ RET // Return to caller
+
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_thread_system_return.S b/ports/cortex_a72/gnu/src/tx_thread_system_return.S
new file mode 100644
index 00000000..7d42b63d
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_thread_system_return.S
@@ -0,0 +1,151 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX system. Only a */
+/* minimal context is saved since the compiler assumes temp registers */
+/* are going to get slicked by a function call anyway. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_schedule Thread scheduling loop */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ .global _tx_thread_system_return
+ .type _tx_thread_system_return, @function
+_tx_thread_system_return:
+
+ /* Save minimal context on the stack. */
+
+ MRS x0, DAIF // Pickup DAIF
+ MSR DAIFSet, 0x3 // Lockout interrupts
+ STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
+ STP x19, x20, [sp, #-16]! // Save x19, x20
+ STP x21, x22, [sp, #-16]! // Save x21, x22
+ STP x23, x24, [sp, #-16]! // Save x23, x24
+ STP x25, x26, [sp, #-16]! // Save x25, x26
+ STP x27, x28, [sp, #-16]! // Save x27, x28
+ LDR x5, =_tx_thread_current_ptr // Pickup address of current ptr
+ LDR x6, [x5, #0] // Pickup current thread pointer
+
+#ifdef ENABLE_ARM_FP
+ LDR w7, [x6, #248] // Pickup FP enable flag
+ CMP w7, #0 // Is FP enabled?
+ BEQ _skip_fp_save // No, skip FP save
+ STP q8, q9, [sp, #-32]! // Save q8, q9
+ STP q10, q11, [sp, #-32]! // Save q10, q11
+ STP q12, q13, [sp, #-32]! // Save q12, q13
+ STP q14, q15, [sp, #-32]! // Save q14, q15
+ MRS x2, FPSR // Pickup FPSR
+ MRS x3, FPCR // Pickup FPCR
+ STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
+_skip_fp_save:
+#endif
+
+ MOV x1, #0 // Clear x1
+ STP x0, x1, [sp, #-16]! // Save DAIF and clear value for ELR_EK1
+
+#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
+
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+
+ MOV x19, x5 // Save x5
+ MOV x20, x6 // Save x6
+ BL _tx_execution_thread_exit // Call the thread exit function
+ MOV x5, x19 // Restore x5
+ MOV x6, x20 // Restore x6
+#endif
+
+ LDR x2, =_tx_timer_time_slice // Pickup address of time slice
+ LDR w1, [x2, #0] // Pickup current time slice
+
+ /* Save current stack and switch to system stack. */
+ // _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
+ // sp = _tx_thread_system_stack_ptr;
+
+ MOV x4, sp //
+ STR x4, [x6, #8] // Save thread stack pointer
+ LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
+ LDR x4, [x3, #0] // Pickup system stack pointer
+ MOV sp, x4 // Setup system stack pointer
+
+ /* Determine if the time-slice is active. */
+ // if (_tx_timer_time_slice)
+ // {
+
+ MOV x4, #0 // Build clear value
+ CMP w1, #0 // Is a time-slice active?
+ BEQ __tx_thread_dont_save_ts // No, don't save the time-slice
+
+ /* Save the current remaining time-slice. */
+ // _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
+ // _tx_timer_time_slice = 0;
+
+ STR w4, [x2, #0] // Clear time-slice
+ STR w1, [x6, #36] // Store current time-slice
+
+ // }
+__tx_thread_dont_save_ts:
+
+ /* Clear the current thread pointer. */
+ // _tx_thread_current_ptr = TX_NULL;
+
+ STR x4, [x5, #0] // Clear current thread pointer
+
+ B _tx_thread_schedule // Jump to scheduler!
+
+// }
diff --git a/ports/cortex_a72/gnu/src/tx_timer_interrupt.S b/ports/cortex_a72/gnu/src/tx_timer_interrupt.S
new file mode 100644
index 00000000..5810b5c2
--- /dev/null
+++ b/ports/cortex_a72/gnu/src/tx_timer_interrupt.S
@@ -0,0 +1,228 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) Microsoft Corporation. All rights reserved. */
+/* */
+/* This software is licensed under the Microsoft Software License */
+/* Terms for Microsoft Azure RTOS. Full text of the license can be */
+/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
+/* and in the root directory of this software. */
+/* */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** ThreadX Component */
+/** */
+/** Timer */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+ .text
+ .align 3
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt ARMv8-A */
+/* 6.1.10 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes the hardware timer interrupt. This */
+/* processing includes incrementing the system clock and checking for */
+/* time slice and/or timer expiration. If either is found, the */
+/* interrupt context save/restore functions are called along with the */
+/* expiration functions. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ .global _tx_timer_interrupt
+ .type _tx_timer_interrupt, @function
+_tx_timer_interrupt:
+
+ /* Upon entry to this routine, it is assumed that context save has already
+ been called, and therefore the compiler scratch registers are available
+ for use. */
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR x1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR w0, [x1, #0] // Pickup system clock
+ ADD w0, w0, #1 // Increment system clock
+ STR w0, [x1, #0] // Store new system clock
+
+ /* Test for time-slice expiration. */
+ /* if (_tx_timer_time_slice)
+ { */
+
+ LDR x3, =_tx_timer_time_slice // Pickup address of time-slice
+ LDR w2, [x3, #0] // Pickup time-slice
+ CMP w2, #0 // Is it non-active?
+ BEQ __tx_timer_no_time_slice // Yes, skip time-slice processing
+
+ /* Decrement the time_slice. */
+ /* _tx_timer_time_slice--; */
+
+ SUB w2, w2, #1 // Decrement the time-slice
+ STR w2, [x3, #0] // Store new time-slice value
+
+ /* Check for expiration. */
+ /* if (__tx_timer_time_slice == 0) */
+
+ CMP w2, #0 // Has it expired?
+ BNE __tx_timer_no_time_slice // No, skip expiration processing
+
+ /* Set the time-slice expired flag. */
+ /* _tx_timer_expired_time_slice = TX_TRUE; */
+
+ LDR x3, =_tx_timer_expired_time_slice // Pickup address of expired flag
+ MOV w0, #1 // Build expired value
+ STR w0, [x3, #0] // Set time-slice expiration flag
+
+ /* } */
+
+__tx_timer_no_time_slice:
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR x1, =_tx_timer_current_ptr // Pickup current timer pointer addr
+ LDR x0, [x1, #0] // Pickup current timer
+ LDR x2, [x0, #0] // Pickup timer list entry
+ CMP x2, #0 // Is there anything in the list?
+ BEQ __tx_timer_no_timer // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR x3, =_tx_timer_expired // Pickup expiration flag address
+ MOV w2, #1 // Build expired value
+ STR w2, [x3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer:
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD x0, x0, #8 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR x3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR x2, [x3, #0] // Pickup list end
+ CMP x0, x2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR x3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR x0, [x3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap:
+
+ STR x0, [x1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done:
+
+
+ /* See if anything has expired. */
+ // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
+ //{
+
+ LDR x3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
+ LDR w2, [x3, #0] // Pickup time-slice expired flag
+ CMP w2, #0 // Did a time-slice expire?
+ BNE __tx_something_expired // If non-zero, time-slice expired
+ LDR x1, =_tx_timer_expired // Pickup addr of other expired flag
+ LDR w0, [x1, #0] // Pickup timer expired flag
+ CMP w0, #0 // Did a timer expire?
+ BEQ __tx_timer_nothing_expired // No, nothing expired
+
+__tx_something_expired:
+
+
+ STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR x1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR w0, [x1, #0] // Pickup timer expired flag
+ CMP w0, #0 // Check for timer expiration
+ BEQ __tx_timer_dont_activate // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate:
+
+ /* Did time slice expire? */
+ // if (_tx_timer_expired_time_slice)
+ // {
+
+ LDR x3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
+ LDR w2, [x3, #0] // Pickup the actual flag
+ CMP w2, #0 // See if the flag is set
+ BEQ __tx_timer_not_ts_expiration // No, skip time-slice processing
+
+ /* Time slice interrupted thread. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+
+ // }/
+
+__tx_timer_not_ts_expiration:
+
+ LDP x29, x30, [sp], #16 // Recover x29, x30
+ // }
+
+__tx_timer_nothing_expired:
+
+ RET // Return to caller
+
+// }