summaryrefslogtreecommitdiff
path: root/ports_smp
diff options
context:
space:
mode:
authorTiejun Zhou <[email protected]>2022-10-26 23:41:13 +0000
committerTiejun Zhou <[email protected]>2022-10-26 23:41:13 +0000
commit3e8e85cdc1e51f9de577457377a4f9a4f6b9b82f (patch)
tree861c0ab74e5dc5de7509b4b85f5e75dd74457117 /ports_smp
parentb871c33620f9b58a83e92a33f4ca00025e850c7f (diff)
Release 6.2.0v6.2.0_rel
Diffstat (limited to 'ports_smp')
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.cproject97
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.project27
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.S292
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.h80
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.h42
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.s169
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.h42
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.s123
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.h36
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.s121
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.h67
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.s193
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.c444
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.ld69
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/retarget.c11
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/startup.S610
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.S381
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.h117
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/tx/.cproject90
-rw-r--r--ports_smp/cortex_r8_smp/ac5/example_build/tx/.project48
-rw-r--r--ports_smp/cortex_r8_smp/ac5/inc/tx_port.h412
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_initialize_low_level.s99
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_restore.s275
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s191
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_control.s91
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_disable.s85
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_restore.s74
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_end.s98
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_start.s92
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_schedule.s249
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_get.s72
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_preempt.s89
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_state_get.s91
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_thread_get.s90
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_initialize_wait.s128
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_low_level_initialize.s72
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_protect.s127
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s75
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_unprotect.s119
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_stack_build.s159
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s193
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s197
-rw-r--r--ports_smp/cortex_r8_smp/ac5/src/tx_timer_interrupt.s214
43 files changed, 6351 insertions, 0 deletions
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.cproject b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.cproject
new file mode 100644
index 00000000..cb9aa7c8
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.cproject
@@ -0,0 +1,97 @@
+<?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.baremetal.exe.debug.base.1803240871">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.baremetal.exe.debug.base.1803240871" 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="com.arm.eclipse.builder.armcc.error" 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.baremetal.exe.debug.base.1803240871" name="Debug" parent="com.arm.eclipse.build.config.baremetal.exe.debug.base">
+ <folderInfo id="com.arm.eclipse.build.config.baremetal.exe.debug.base.1803240871." name="/" resourcePath="">
+ <toolChain id="com.arm.toolchain.baremetal.374109035" name="Arm Compiler 5 (DS-5 built-in)" superClass="com.arm.toolchain.baremetal">
+ <option id="com.arm.toolchain.ac5.option.target.cpu_fpu.1442008928" superClass="com.arm.toolchain.ac5.option.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R8.VFPv3_D16_FP16" valueType="string"/>
+ <option id="com.arm.toolchain.ac5.option.fppcs.1860512958" name="Floating-point PCS" superClass="com.arm.toolchain.ac5.option.fppcs" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.toolchain.ac5.option.inst.1449330817" name="Instruction set" superClass="com.arm.toolchain.ac5.option.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <targetPlatform id="com.arm.toolchain.baremetal.374109035.836409078" name=""/>
+ <builder buildPath="${workspace_loc:/demo_threadx}/Debug" id="com.arm.toolchain.baremetal.builder.987677285" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.baremetal.builder"/>
+ <tool id="com.arm.tool.c.compiler.502732960" name="Arm C Compiler 5" superClass="com.arm.tool.c.compiler">
+ <option defaultValue="com.arm.tool.c.compiler.option.optlevel.min" id="com.arm.tool.c.compiler.option.optlevel.2147390479" name="Optimization level" superClass="com.arm.tool.c.compiler.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.targetcpu.340427204" name="Target CPU (--cpu)" superClass="com.arm.tool.c.compiler.option.targetcpu" useByScannerDiscovery="true" value="Cortex-R8" valueType="string"/>
+ <option id="com.arm.tool.c.compiler.option.fppcs.577495892" name="Floating-point PCS (--apcs)" superClass="com.arm.tool.c.compiler.option.fppcs" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.inst.1235707985" name="Instruction set" superClass="com.arm.tool.c.compiler.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.incpath.1124000016" name="Include path (-I)" superClass="com.arm.tool.c.compiler.option.incpath" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/tx/inc_port}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/tx/inc_generic}&quot;"/>
+ </option>
+ <inputType id="com.arm.tool.c.compiler.input.1480260868" superClass="com.arm.tool.c.compiler.input"/>
+ <inputType id="com.arm.tool.cpp.compiler.input.97641973" superClass="com.arm.tool.cpp.compiler.input"/>
+ </tool>
+ <tool id="com.arm.tool.cpp.compiler.1547990840" name="Arm C++ Compiler 5" superClass="com.arm.tool.cpp.compiler">
+ <option defaultValue="com.arm.tool.c.compiler.option.optlevel.min" id="com.arm.tool.c.compiler.option.optlevel.505573824" name="Optimization level" superClass="com.arm.tool.c.compiler.option.optlevel" valueType="enumerated"/>
+ </tool>
+ <tool id="com.arm.tool.assembler.1832506761" name="Arm Assembler 5" superClass="com.arm.tool.assembler">
+ <option id="com.arm.tool.assembler.option.cpu.1024239032" name="Target CPU (--cpu)" superClass="com.arm.tool.assembler.option.cpu" useByScannerDiscovery="true" value="Cortex-R8" valueType="string"/>
+ <option id="com.arm.tool.assembler.option.fppcs.390080950" name="Floating-point PCS (--apcs)" superClass="com.arm.tool.assembler.option.fppcs" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.tool.assembler.option.inst.1329777569" name="Instruction set" superClass="com.arm.tool.assembler.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <option id="com.arm.tool.assembler.option.preproc.1552112760" name="Preprocess input before assembling (--cpreproc)" superClass="com.arm.tool.assembler.option.preproc" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+ <inputType id="com.arm.tool.assembler.input.568650196" superClass="com.arm.tool.assembler.input"/>
+ </tool>
+ <tool id="com.arm.tool.c.linker.1213717379" name="Arm Linker 5" superClass="com.arm.tool.c.linker">
+ <option id="com.arm.tool.c.linker.option.cpu.2034204217" name="Target CPU (--cpu)" superClass="com.arm.tool.c.linker.option.cpu" useByScannerDiscovery="true" value="Cortex-R8" valueType="string"/>
+ <option id="com.arm.tool.c.linker.libs.1039233109" name="User library files" superClass="com.arm.tool.c.linker.libs" useByScannerDiscovery="false" valueType="libs">
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/tx/Debug/tx.a}&quot;"/>
+ </option>
+ <option id="com.arm.tool.c.linker.option.scatter.273877226" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" useByScannerDiscovery="false" value="../demo_threadx.ld" valueType="string"/>
+ </tool>
+ <tool id="com.arm.tool.librarian.929712312" name="Arm Librarian 5" superClass="com.arm.tool.librarian"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="com.arm.eclipse.build.config.baremetal.exe.release.base.1220518793">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.baremetal.exe.release.base.1220518793" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <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"/>
+ </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.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.baremetal.exe.release.base.1220518793" name="Release" parent="com.arm.eclipse.build.config.baremetal.exe.release.base">
+ <folderInfo id="com.arm.eclipse.build.config.baremetal.exe.release.base.1220518793." name="/" resourcePath="">
+ <toolChain id="com.arm.toolchain.baremetal.exe.release.base.var.arm_compiler_5-5.6.7.997372112" name="Arm Compiler 5.06u7">
+ <targetPlatform id="com.arm.toolchain.baremetal.exe.release.base.var.arm_compiler_5-5.6.7.997372112.1793920751" name=""/>
+ <builder autoBuildTarget="all" buildPath="${workspace_loc:/demo_threadx}/Release" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.baremetal.builder.1590448126" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="false" superClass="com.arm.toolchain.baremetal.builder"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="cortex-r8_demo_threadx.com.arm.eclipse.build.project.baremetal.exe.1823514114" 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="/cortex-r8_demo_threadx"/>
+ </configuration>
+ <configuration configurationName="Release">
+ <resource resourceType="PROJECT" workspacePath="/cortex-r8_demo_threadx"/>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+ <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+</cproject>
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.project b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.project
new file mode 100644
index 00000000..29c218ae
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/.project
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>demo_threadx</name>
+ <comment></comment>
+ <projects>
+ <project>cortex-r8_tx</project>
+ </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_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.S b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.S
new file mode 100644
index 00000000..eb1f366e
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.S
@@ -0,0 +1,292 @@
+; ------------------------------------------------------------
+; Cortex-R MPCore - Interrupt Controller functions
+;
+; Copyright ARM Ltd 2009. All rights reserved.
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA MP_GIC, CODE, READONLY
+
+; ------------------------------------------------------------
+; GIC
+; ------------------------------------------------------------
+
+ ; CPU Interface offset from base of private peripheral space --> 0x0100
+ ; Interrupt Distributor offset from base of private peripheral space --> 0x1000
+
+ ; Typical calls to enable interrupt ID X:
+ ; enable_irq_id(X) <-- Enable that ID
+ ; set_irq_priority(X, 0) <-- Set the priority of X to 0 (the max priority)
+ ; set_priority_mask(0x1F) <-- Set CPU's priority mask to 0x1F (the lowest priority)
+ ; enable_GIC() <-- Enable the GIC (global)
+ ; enable_gic_processor_interface() <-- Enable the CPU interface (local to the CPU)
+
+
+ EXPORT enable_GIC
+ ; void enable_GIC(void)
+ ; Global enable of the Interrupt Distributor
+enable_GIC PROC
+
+ ; Get base address of private perpherial space
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+ ADD r0, r0, #0x1000 ; Add the GIC offset
+
+ LDR r1, [r0] ; Read the GIC's Enable Register (ICDDCR)
+ ORR r1, r1, #0x01 ; Set bit 0, the enable bit
+ STR r1, [r0] ; Write the GIC's Enable Register (ICDDCR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT disable_GIC
+ ; void disable_GIC(void)
+ ; Global disable of the Interrupt Distributor
+disable_GIC PROC
+
+ ; Get base address of private perpherial space
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+ ADD r0, r0, #0x1000 ; Add the GIC offset
+
+ LDR r1, [r0] ; Read the GIC's Enable Register (ICDDCR)
+ BIC r1, r1, #0x01 ; Set bit 0, the enable bit
+ STR r1, [r0] ; Write the GIC's Enable Register (ICDDCR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT enable_irq_id
+ ; void enable_irq_id(unsigned int ID)
+ ; Enables the interrupt source number ID
+enable_irq_id PROC
+
+ ; Get base address of private perpherial space
+ MOV r1, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; Each interrupt source has an enable bit in the GIC. These
+ ; are grouped into registers, with 32 sources per register
+ ; First, we need to identify which 32 bit block the interrupt lives in
+ MOV r2, r1 ; Make working copy of ID in r2
+ MOV r2, r2, LSR #5 ; LSR by 5 places, affective divide by 32
+ ; r2 now contains the 32 bit block this ID lives in
+ MOV r2, r2, LSL #2 ; Now multiply by 4, to covert offset into an address offset (four bytes per reg)
+
+ ; Now work out which bit within the 32 bit block the ID is
+ AND r1, r1, #0x1F ; Mask off to give offset within 32bit block
+ MOV r3, #1 ; Move enable value into r3
+ MOV r3, r3, LSL r1 ; Shift it left to position of ID
+
+ ADD r2, r2, #0x1100 ; Add the base offset of the Enable Set registers to the offset for the ID
+ STR r3, [r0, r2] ; Store out (ICDISER)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT disable_irq_id
+ ; void disable_irq_id(unsigned int ID)
+ ; Disables the interrupt source number ID
+disable_irq_id PROC
+
+ ; Get base address of private perpherial space
+ MOV r1, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; First, we need to identify which 32 bit block the interrupt lives in
+ MOV r2, r1 ; Make working copy of ID in r2
+ MOV r2, r2, LSR #5 ; LSR by 5 places, affective divide by 32
+ ; r2 now contains the 32 bit block this ID lives in
+ MOV r2, r2, LSL #2 ; Now multiply by 4, to covert offset into an address offset (four bytes per reg)
+
+ ; Now work out which bit within the 32 bit block the ID is
+ AND r1, r1, #0x1F ; Mask off to give offset within 32bit block
+ MOV r3, #1 ; Move enable value into r3
+ MOV r3, r3, LSL r1 ; Shift it left to position of ID in 32 bit block
+
+ ADD r2, r2, #0x1180 ; Add the base offset of the Enable Clear registers to the offset for the ID
+ STR r3, [r0, r2] ; Store out (ICDICER)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT set_irq_priority
+ ; void set_irq_priority(unsigned int ID, unsigned int priority)
+ ; Sets the priority of the specifed ID
+ ; r0 = ID
+ ; r1 = priority
+set_irq_priority PROC
+
+ ; Get base address of private perpherial space
+ MOV r2, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; r0 = base addr
+ ; r1 = priority
+ ; r2 = ID
+
+ ; Make sure that priority value is only 5 bits, and convert to expected format
+ AND r1, r1, #0x1F
+ MOV r1, r1, LSL #3
+
+ ; Find which priority register this ID lives in
+ BIC r3, r2, #0x03 ; Make a copy of the ID, clearing off the bottom two bits
+ ; There are four IDs per reg, by clearing the bottom two bits we get an address offset
+ ADD r3, r3, #0x1400 ; Now add the offset of the Priority Level registers from the base of the private peripheral space
+ ADD r0, r0, r3 ; Now add in the base address of the private peripheral space, giving us the absolute address
+
+
+ ; Now work out which ID in the register it is
+ AND r2, r2, #0x03 ; Clear all but the bottom four bits, leaves which ID in the reg it is (which byte)
+ MOV r2, r2, LSL #3 ; Multiply by 8, this gives a bit offset
+
+ ; Read -> Modify -> Write
+ MOV r12, #0xFF ; Mask (8 bits)
+ MOV r12, r12, LSL r2 ; Move mask into correct bit position
+ MOV r1, r1, LSL r2 ; Also, move passed in priority value into correct bit position
+
+ LDR r3, [r0] ; Read current value of the Priority Level register (ICDIPR)
+ BIC r3, r3, r12 ; Clear appropiate field
+ ORR r3, r3, r1 ; Now OR in the priority value
+ STR r3, [r0] ; And store it back again (ICDIPR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT enable_gic_processor_interface
+ ; void enable_gic_processor_interface(void)
+ ; Enables the processor interface
+ ; Must been done one each CPU seperately
+enable_gic_processor_interface PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x100] ; Read the Processor Interface Control register (ICCICR/ICPICR)
+ ORR r1, r1, #0x03 ; Bit 0: Enables secure interrupts, Bit 1: Enables Non-Secure interrupts
+ STR r1, [r0, #0x100] ; Write the Processor Interface Control register (ICCICR/ICPICR)
+
+ BX lr
+ ENDP
+
+
+; ------------------------------------------------------------
+
+ EXPORT disable_gic_processor_interface
+ ; void disable_gic_processor_interface(void)
+ ; Disables the processor interface
+ ; Must been done one each CPU seperately
+disable_gic_processor_interface PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x100] ; Read the Processor Interface Control register (ICCICR/ICPICR)
+ BIC r1, r1, #0x03 ; Bit 0: Enables secure interrupts, Bit 1: Enables Non-Secure interrupts
+ STR r1, [r0, #0x100] ; Write the Processor Interface Control register (ICCICR/ICPICR)
+
+ BX lr
+ ENDP
+
+
+; ------------------------------------------------------------
+
+ EXPORT set_priority_mask
+ ; void set_priority_mask(unsigned int priority)
+ ; Sets the Priority mask register for the CPU run on
+ ; The reset value masks ALL interrupts!
+set_priority_mask PROC
+
+ ; Get base address of private perpherial space
+ MOV r1, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ STR r1, [r0, #0x0104] ; Write the Priority Mask register (ICCPMR/ICCIPMR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT set_binary_port
+ ; void set_binary_port(unsigned int priority)
+ ; Sets the Binary Point Register for the CPU run on
+set_binary_port PROC
+
+ ; Get base address of private perpherial space
+ MOV r1, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ STR r1, [r0, #0x0108] ; Write the Binary register (ICCBPR/ICCBPR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT read_irq_ack
+ ; unsigned int read_irq_ack(void)
+ ; Returns the value of the Interrupt Acknowledge Register
+read_irq_ack PROC
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+ LDR r0, [r0, #0x010C] ; Read the Interrupt Acknowledge Register (ICCIAR)
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT write_end_of_irq
+ ; void write_end_of_irq(unsigned int ID)
+ ; Writes ID to the End Of Interrupt register
+write_end_of_irq PROC
+
+ ; Get base address of private perpherial space
+ MOV r1, r0 ; Back up passed in ID value
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ STR r1, [r0, #0x0110] ; Write ID to the End of Interrupt register (ICCEOIR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; SGI
+; ------------------------------------------------------------
+
+ EXPORT send_sgi
+ ; void send_sgi(unsigned int ID, unsigned int target_list, unsigned int filter_list);
+ ; Send a software generate interrupt
+send_sgi PROC
+
+ AND r3, r0, #0x0F ; Mask off unused bits of ID, and move to r3
+ AND r1, r1, #0x0F ; Mask off unused bits of target_filter
+ AND r2, r2, #0x0F ; Mask off unused bits of filter_list
+
+ ORR r3, r3, r1, LSL #16 ; Combine ID and target_filter
+ ORR r3, r3, r2, LSL #24 ; and now the filter list
+
+ ; Get the address of the GIC
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+ ADD r0, r0, #0x1F00 ; Add offset of the sgi_trigger reg
+
+ STR r3, [r0] ; Write to the Software Generated Interrupt Register (ICDSGIR)
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of MP_GIC.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.h
new file mode 100644
index 00000000..81551bee
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GIC.h
@@ -0,0 +1,80 @@
+// ------------------------------------------------------------
+// Cortex-R MPCore - Interrupt Controller functions
+// Header File
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _CORTEXA_GIC_
+#define _CORTEXA_GIC_
+
+// ------------------------------------------------------------
+// GIC
+// ------------------------------------------------------------
+
+// Typical calls to enable interrupt ID X:
+// enable_irq_id(X) <-- Enable that ID
+// set_irq_priority(X, 0) <-- Set the priority of X to 0 (the max priority)
+// set_priority_mask(0x1F) <-- Set Core's priority mask to 0x1F (the lowest priority)
+// enable_GIC() <-- Enable the GIC (global)
+// enable_gic_processor_interface() <-- Enable the CPU interface (local to the core)
+//
+// OR
+//
+// Use init_GIC() which is a simple switch everything on function! :-)
+//
+
+// Global enable of the Interrupt Distributor
+void enable_GIC(void);
+
+// Global disable of the Interrupt Distributor
+void disable_GIC(void);
+
+// Enables the interrupt source number ID
+void enable_irq_id(unsigned int ID);
+
+// Disables the interrupt source number ID
+void disable_irq_id(unsigned int ID);
+
+// Sets the priority of the specifed ID
+void set_irq_priority(unsigned int ID, unsigned int priority);
+
+// Enables the processor interface
+// Must been done one each core seperately
+void enable_gic_processor_interface(void);
+
+// Disables the processor interface
+void disable_gic_processor_interface(void);
+
+// Sets the Priority mask register for the core run on
+// The reset value masks ALL interrupts!
+void set_priority_mask(unsigned int priority);
+
+// Sets the Binary Point Register for the core run on
+void set_binary_port(unsigned int priority);
+
+// Returns the value of the Interrupt Acknowledge Register
+unsigned int read_irq_ack(void);
+
+// Writes ID to the End Of Interrupt register
+void write_end_of_irq(unsigned int ID);
+
+// Lazy Init function, a quick way of enabling interrupts
+// * Enables the GIC (global) and CPU Interface (just for this core)
+// * Enables interrupt sources 0->31, and sets their priority to 0x0
+// * Sets the CPU's Priority mask to 0x1F
+// * Clears the CPSR I bit
+void init_GIC(void);
+
+// ------------------------------------------------------------
+// SGI
+// ------------------------------------------------------------
+
+// Send a software generate interrupt
+void send_sgi(unsigned int ID, unsigned int core_list, unsigned int filter_list);
+
+#endif
+
+// ------------------------------------------------------------
+// End of MP_GIC.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.h
new file mode 100644
index 00000000..7a272b3e
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.h
@@ -0,0 +1,42 @@
+// ------------------------------------------------------------
+// Cortex-R MPCore - Global timer functions
+// Header Filer
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _CORTEXA_GLOBAL_TIMER_
+#define _CORTEXA_GLOBAL_TIMER_
+
+// Typical set of calls to enable Timer:
+// init_global_timer( AUTO_INCREMENT>, INCREMENT_VALUE );
+// set_global_timer_comparator( UPPER_32_BITS, LOWER_32_BITS );
+// start_global_timer();
+
+
+// Sets up the private timer
+// r0: IF 0 (AutoIncrement) ELSE (SingleShot)
+// r1: Increment value (ignored if auto_increment != 0)
+void init_global_timer(unsigned int auto_increment, unsigned int increment_value)
+
+// Sets the comparator value for this CPU
+void set_global_timer_comparator(unsigned int top, unsigned int bottom);
+
+// Starts the private timer
+void start_global_timer(void);
+
+// Stops the private timer
+void stop_global_timer(void);
+
+// Reads the current value of the timer count register
+// Returns bits 63:32 in *top, and bits 31:0 in *bottom
+void read_global_timer(unsigned int* top, unsigned int* bottom);
+
+// Clears the private timer interrupt
+void clear_global_timer_irq(void);
+
+#endif
+
+// ------------------------------------------------------------
+// End of MP_PrivateTimer.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.s b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.s
new file mode 100644
index 00000000..04245587
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_GlobalTimer.s
@@ -0,0 +1,169 @@
+; ------------------------------------------------------------
+; Cortex-R MPCore - Global timer functions
+;
+; Copyright ARM Ltd 2009. All rights reserved.
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA MP_PrivateTimer, CODE, READONLY
+
+ ; PPI ID 27
+
+
+ ; Typical set of calls to enable Timer:
+ ; init_global_timer()
+ ; set_global_timer_comparator()
+ ; start_global_timer()
+
+; ------------------------------------------------------------
+
+ EXPORT init_global_timer
+ ; void init_global_timer(unsigned int auto_increment, unsigned int increment_value)
+ ; Initializes the Global Timer, but does NOT set the enable bit
+ ; r0: IF 0 (AutoIncrement) ELSE (SingleShot)
+ ; r1: increment value
+init_global_timer PROC
+
+ ; Get base address of private perpherial space
+ MRC p15, 4, r2, c15, c0, 0 ; Read periph base address
+
+ ; Control register bit layout
+ ; Bit 0 - Timer enable
+ ; Bit 1 - Comp enable
+ ; Bit 2 - IRQ enable
+ ; Bit 3 - Auto-increment enable
+
+ ; Ensure the timer is disabled
+ LDR r3, [r2, #0x208] ; Read control reg
+ BIC r3, r3, #0x01 ; Clear enable bit
+ STR r3, [r2, #0x208] ; Write control reg
+
+ ; Form control reg value
+ CMP r0, #0 ; Check whether to enable auto-reload
+ MOVNE r0, #0x00 ; No auto-reload
+ MOVEQ r0, #0x04 ; With auto-reload
+ STR r0, [r2, #0x208] ; Store to control register
+
+ ; Store increment value
+ STREQ r1, [r2, #0x218]
+
+ ; Clear timer value
+ MOV r0, #0x0
+ STR r0, [r2, #0x0]
+ STR r0, [r2, #0x4]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT set_global_timer_comparator
+ ; void set_global_timer_comparator(unsigned int top, unsigned int bottom);
+ ; Writes the comparator registers, and enable the comparator bit in the control register
+ ; r0: 63:32 of the comparator value
+ ; r1: 31:0 of the comparator value
+set_global_timer_comparator PROC
+
+ MRC p15, 4, r2, c15, c0, 0 ; Read periph base address
+
+ ; Disable comparator before updating register
+ LDR r1, [r2, #0x208] ; Read control reg
+ BIC r3, r3, #0x02 ; Clear comparator enable bit
+ STR r3, [r2, #0x208] ; Write modified value back
+
+ ; Write the comparator registers
+ STR r1, [r2, #0x210] ; Write lower 32 bits
+ STR r0, [r2, #0x214] ; Write upper 32 bits
+ DMB
+
+ ; Re-enable the comparator
+ ORR r3, r3, #0x02 ; Set comparator enable bit
+ STR r3, [r2, #0x208] ; Write modified value back
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT start_global_timer
+ ; void start_global_timer(void)
+ ; Starts the global timer
+start_global_timer PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x208] ; Read control reg
+ ORR r1, r1, #0x01 ; Set enable bit
+ STR r1, [r0, #0x208] ; Write modified value back
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT stop_global_timer
+ ; void stop_private_timer(void)
+ ; Stops the private timer
+;stop_private_timer PROC
+stop_global_timer PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x208] ; Read control reg
+ BIC r1, r1, #0x01 ; Clear enable bit
+ STR r1, [r0, #0x208] ; Write modified value back
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT get_global_timer_count
+ ; void read_global_timer(unsigned int* top, unsigned int* bottom)
+ ; Reads the current value of the timer count register
+ ; r0: Address of unsigned int for bits 63:32
+ ; r1: Address of unsigned int for bits 31:0
+get_global_timer_count PROC
+
+get_global_timer_count_loop
+ MRC p15, 4, r2, c15, c0, 0 ; Read periph base address
+
+ LDR r12,[r2, #0x04] ; Read bits 63:32
+ LDR r3, [r2, #0x00] ; Read bits 31:0
+ LDR r2, [r2, #0x04] ; Re-read bits 63:32
+
+ CMP r2, r12 ; Have the top bits changed?
+ BNE get_global_timer_count_loop
+
+ ; Store result out to pointers
+ STR r2, [r0]
+ STR r3, [r1]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT clear_global_timer_irq
+ ; void clear_global_timer_irq(void)
+ ; Clears the global timer interrupt
+clear_global_timer_irq PROC
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; Clear the interrupt by writing 0x1 to the Timer's Interrupt Status register
+ MOV r1, #1
+ STR r1, [r0, #0x20C]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of MP_GlobalTimer.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.h
new file mode 100644
index 00000000..2a613b7e
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.h
@@ -0,0 +1,42 @@
+// ------------------------------------------------------------
+// Cortex-R MPCore - Mutex
+// Header File
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _CORTEXA_MUTEX_
+#define _CORTEXA_MUTEX_
+
+// Struct
+// 0xFF=unlocked 0x0 = Locked by CPU 0,
+// 0x1 = Locked by CPU 1,
+// 0x2 = Locked by CPU 2,
+// 0x3 = Locked by CPU 3
+typedef struct
+{
+ unsigned int lock;
+}mutex_t;
+
+// Places mutex into a known state
+// r0 = address of mutex_t
+void init_mutex(mutex_t* pMutex);
+
+// Blocking call, returns once successfully locked a mutex
+// r0 = address of mutex_t
+void lock_mutex(mutex_t* pMutex);
+
+// Releases (unlock) mutex. Fails if CPU not owner of mutex.
+// returns 0x0 for success, and 0x1 for failure
+// r0 = address of mutex_t
+unsigned int unlock_mutex(mutex_t* pMutex);
+
+// Returns 0x0 if mutex unlocked, 0x1 is locked
+// r0 = address of mutex_t
+void is_mutex_locked(mutex_t* pMutex);
+
+#endif
+
+// ------------------------------------------------------------
+// End of MP_Mutexes.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.s b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.s
new file mode 100644
index 00000000..3c20b253
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_Mutexes.s
@@ -0,0 +1,123 @@
+; ------------------------------------------------------------
+; Cortex-R MPCore - Mutex Code
+;
+; Copyright ARM Ltd 2009. All rights reserved.
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA MP_Mutexes, CODE, READONLY
+
+ ;NOTES
+ ; struct mutex_t defined in A9MP_Mutexes.h
+ ; typedef struct mutex_t
+ ; {
+ ; unsigned int lock; <-- offset 0
+ ; }
+ ;
+ ; lock: 0xFF=unlocked 0x0 = Locked by CPU 0, 0x1 = Locked by CPU 1, 0x2 = Locked by CPU 2, 0x3 = Locked by CPU 3
+ ;
+
+UNLOCKED EQU 0xFF
+
+; ------------------------------------------------------------
+
+ EXPORT init_mutex
+ ; void init_mutex(mutex_t* pMutex)
+ ; Places mutex into a known state
+ ; r0 = address of mutex_t
+init_mutex PROC
+
+ MOV r1, #UNLOCKED ; Mark as unlocked
+ STR r1, [r0]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT lock_mutex
+ ; void lock_mutex(mutex_t* pMutex)
+ ; Blocking call, returns once successfully locked a mutex
+ ; r0 = address of mutex_t
+lock_mutex PROC
+
+ ; Is mutex locked?
+ ; -----------------
+ LDREX r1, [r0] ; Read lock field
+ CMP r1, #UNLOCKED ; Compare with "unlocked"
+
+ WFENE ; If mutex is locked, go into standby
+ BNE lock_mutex ; On waking re-check the mutex
+
+ ; Attempt to lock mutex
+ ; -----------------------
+ MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register
+ AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field.
+ STREX r2, r1, [r0] ; Attempt to lock mutex, by write CPU's ID to lock field
+ CMP r2, #0x0 ; Check wether store completed successfully (0=succeeded)
+ BNE lock_mutex ; If store failed, go back to beginning and try again
+
+ DMB
+
+ BX lr ; Return as mutex is now locked by this cpu
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT unlock_mutex
+ ; unsigned int unlock_mutex(mutex_t* pMutex)
+ ; Releases mutex, returns 0x0 for success and 0x1 for failure
+ ; r0 = address of mutex_t
+unlock_mutex PROC
+
+ ; Does this CPU own the mutex?
+ ; -----------------------------
+ MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register
+ AND r1, r1, #0x03 ; Mask off, leaving the CPU ID in r1
+ LDR r2, [r0] ; Read the lock field of the mutex
+ CMP r1, r2 ; Compare ID of this CPU with the lock owner
+ MOVNE r0, #0x1 ; If ID doesn't match, return "fail"
+ BXNE lr
+
+
+ ; Unlock mutex
+ ; -------------
+ DMB ; Ensure that accesses to shared resource have completed
+
+ MOV r1, #UNLOCKED ; Write "unlocked" into lock field
+ STR r1, [r0]
+
+ DMB ; To ensure update of the mutex occurs before other CPUs awake
+
+ SEV ; Send event to other CPUs, wakes anyone waiting on a mutex (using WFE)
+
+ MOV r0, #0x0 ; Return "success"
+ BX lr
+
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT is_mutex_locked
+ ; void is_mutex_locked(mutex_t* pMutex)
+ ; Returns 0x0 if mutex unlocked, 0x1 is locked
+ ; r0 = address of mutex_t
+is_mutex_locked PROC
+ LDR r0, [r0]
+ CMP r0, #UNLOCKED
+ MOVEQ r0, #0x0
+ MOVNE r0, #0x1
+ BX lr
+ ENDP
+
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of MP_Mutexes.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.h
new file mode 100644
index 00000000..cd0d37f8
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.h
@@ -0,0 +1,36 @@
+// ------------------------------------------------------------
+// Cortex-R MPCore - Private timer functions
+// Header Filer
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _CORTEXA_PRIVATE_TIMER_
+#define _CORTEXA_PRIVATE_TIMER_
+
+// Typical set of calls to enable Timer:
+// init_private_timer(0xXXXX, 0) <-- Counter down value of 0xXXXX, with auto-reload
+// start_private_timer()
+
+// Sets up the private timer
+// r0: initial load value
+// r1: IF 0 (AutoReload) ELSE (SingleShot)
+void init_private_timer(unsigned int load_value, unsigned int auto_reload);
+
+// Starts the private timer
+void start_private_timer(void);
+
+// Stops the private timer
+void stop_private_timer(void);
+
+// Reads the current value of the timer count register
+unsigned int get_private_timer_count(void);
+
+// Clears the private timer interrupt
+void clear_private_timer_irq(void);
+
+#endif
+
+// ------------------------------------------------------------
+// End of MP_PrivateTimer.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.s b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.s
new file mode 100644
index 00000000..3be7249b
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_PrivateTimer.s
@@ -0,0 +1,121 @@
+; ------------------------------------------------------------
+; Cortex-R MPCore - Private timer functions
+;
+; Copyright ARM Ltd 2009. All rights reserved.
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA MP_PrivateTimer, CODE, READONLY
+
+ ; PPI ID 29
+
+
+ ; Typical set of calls to enable Timer:
+ ; init_private_timer(0xXXXX, 0) <-- Counter down value of 0xXXXX, with auto-reload
+ ; start_private_timer()
+
+ ; Timer offset from base of private peripheral space --> 0x600
+
+; ------------------------------------------------------------
+
+ EXPORT init_private_timer
+ ; void init_private_timer(unsigned int load_value, unsigned int auto_reload)
+ ; Sets up the private timer
+ ; r0: initial load value
+ ; r1: IF 0 (AutoReload) ELSE (SingleShot)
+init_private_timer PROC
+
+ ; Get base address of private perpherial space
+ MOV r2, r0 ; Make a copy of r0 before corrupting
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; Set the load value
+ STR r2, [r0, #0x600]
+
+ ; Control register bit layout
+ ; Bit 0 - Enable
+ ; Bit 1 - Auto-Reload ; see DE681117
+ ; Bit 2 - IRQ Generation
+
+ ; Form control reg value
+ CMP r1, #0 ; Check whether to enable auto-reload
+ MOVNE r2, #0x04 ; No auto-reload
+ MOVEQ r2, #0x06 ; With auto-reload
+
+ ; Store to control register
+ STR r2, [r0, #0x608]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT start_private_timer
+ ; void start_private_timer(void)
+ ; Starts the private timer
+start_private_timer PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x608] ; Read control reg
+ ORR r1, r1, #0x01 ; Set enable bit
+ STR r1, [r0, #0x608] ; Write modified value back
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT stop_private_timer
+ ; void stop_private_timer(void)
+ ; Stops the private timer
+stop_private_timer PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x608] ; Read control reg
+ BIC r1, r1, #0x01 ; Clear enable bit
+ STR r1, [r0, #0x608] ; Write modified value back
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT get_private_timer_count
+ ; unsigned int read_private_timer(void)
+ ; Reads the current value of the timer count register
+get_private_timer_count PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r0, [r0, #0x604] ; Read count register
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT clear_private_timer_irq
+ ; void clear_private_timer_irq(void)
+ ; Clears the private timer interrupt
+clear_private_timer_irq PROC
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ ; Clear the interrupt by writing 0x1 to the Timer's Interrupt Status register
+ MOV r1, #1
+ STR r1, [r0, #0x60C]
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of MP_PrivateTimer.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.h
new file mode 100644
index 00000000..c9fe4da6
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.h
@@ -0,0 +1,67 @@
+// ------------------------------------------------------------
+// Cortex-R MPCore - Snoop Control Unit
+// Header File
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _CORTEXA_SCU_
+#define _CORTEXA_SCU_
+
+// ------------------------------------------------------------
+// SCU
+// ------------------------------------------------------------
+
+// Returns the base address of the private peripheral memory space
+unsigned int get_base_addr(void);
+
+// Returns the CPU ID (0 to 3) of the CPU executed on
+unsigned int get_cpu_id(void);
+
+// Returns the number of cores in the A9 Cluster
+// NOTE:
+// returns 0 = 1 core
+// 1 = 2 cores etc...
+// This is the format of the register, decided to leave it unchanged.
+unsigned int get_num_cpus(void);
+
+// Go to sleep, never returns
+void go_to_sleep(void);
+
+// ------------------------------------------------------------
+// SCU
+// ------------------------------------------------------------
+
+// Enables the SCU
+void enable_scu(void);
+
+// Set this core as participating in SMP
+void join_smp(void);
+
+// Set this core as NOT participating in SMP
+void leave_smp(void);
+
+// The return value is 1 bit per core:
+// bit 0 - CPU 0
+// bit 1 - CPU 1
+// etc...
+unsigned int get_cpus_in_smp(void);
+
+ //Enable the broadcasting of cache & TLB maintenance operations
+// When enabled AND in SMP, broadcast all "inner sharable"
+// cache and TLM maintenance operations to other SMP cores
+void enable_maintenance_broadcast(void);
+
+// Disable the broadcasting of cache & TLB maintenance operations
+void disable_maintenance_broadcast(void);
+
+// cpu: 0x0=CPU 0 0x1=CPU 1 etc...
+// This function invalidates the SCU copy of the tag rams
+// for the specified core.
+void secure_SCU_invalidate(unsigned int cpu, unsigned int ways);
+
+#endif
+
+// ------------------------------------------------------------
+// End of MP_SCU.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.s b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.s
new file mode 100644
index 00000000..cfed344f
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/MP_SCU.s
@@ -0,0 +1,193 @@
+; ------------------------------------------------------------
+; Cortex-R MPCore - SCU functions
+;
+; Copyright ARM Ltd 2009. All rights reserved.
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA MP_SCU, CODE, READONLY
+
+; ------------------------------------------------------------
+; Misc
+; ------------------------------------------------------------
+
+ EXPORT get_base_addr
+ ; unsigned int get_base_addr(void)
+ ; Returns the base address of the private peripheral memory space
+get_base_addr PROC
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address (see DE593076)
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT get_cpu_id
+ ; unsigned int get_cpu_id(void)
+ ; Returns the CPU ID (0 to 3) of the CPU executed on
+get_cpu_id PROC
+ MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+ AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT get_num_cpus
+ ; unsigned int get_num_cpus(void)
+ ; Returns the number of CPUs in the A9 Cluster
+get_num_cpus PROC
+
+ ; Get base address of private perpherial space
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r0, [r0, #0x004] ; Read SCU Configuration register
+ AND r0, r0, #0x3 ; Bits 1:0 gives the number of cores
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT go_to_sleep
+ ; void go_to_sleep(void)
+go_to_sleep PROC
+ WFI ; Go into standby
+ B go_to_sleep ; Catch in case of rogue events
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; SCU
+; ------------------------------------------------------------
+
+ ; SCU offset from base of private peripheral space --> 0x000
+
+ EXPORT enable_scu
+ ; void enable_scu(void)
+ ; Enables the SCU
+enable_scu PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r1, [r0, #0x0] ; Read the SCU Control Register
+ ORR r1, r1, #0x1 ; Set bit 0 (The Enable bit)
+ STR r1, [r0, #0x0] ; Write back modifed value
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT join_smp
+ ; void join_smp(void)
+ ; Set this CPU as participating in SMP
+join_smp PROC
+
+ ; SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
+
+ MRC p15, 0, r0, c1, c0, 1 ; Read ACTLR
+ ORR r0, r0, #0x040 ; Set bit 6
+ MCR p15, 0, r0, c1, c0, 1 ; Write ACTLR
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT leave_smp
+ ; void leave_smp(void)
+ ; Set this CPU as NOT participating in SMP
+leave_smp PROC
+
+ ; SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
+
+ MRC p15, 0, r0, c1, c0, 1 ; Read ACTLR
+ BIC r0, r0, #0x040 ; Clear bit 6
+ MCR p15, 0, r0, c1, c0, 1 ; Write ACTLR
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT get_cpus_in_smp
+ ; unsigned int get_cpus_in_smp(void)
+ ; The return value is 1 bit per core:
+ ; bit 0 - CPU 0
+ ; bit 1 - CPU 1
+ ; etc...
+get_cpus_in_smp PROC
+
+ MRC p15, 4, r0, c15, c0, 0 ; Read periph base address
+
+ LDR r0, [r0, #0x004] ; Read SCU Configuration register
+ MOV r0, r0, LSR #4 ; Bits 7:4 gives the cores in SMP mode, shift then mask
+ AND r0, r0, #0x0F
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT enable_maintenance_broadcast
+ ; void enable_maintenance_broadcast(void)
+ ; Enable the broadcasting of cache & TLB maintenance operations
+ ; When enabled AND in SMP, broadcast all "inner sharable"
+ ; cache and TLM maintenance operations to other SMP cores
+enable_maintenance_broadcast PROC
+ MRC p15, 0, r0, c1, c0, 1 ; Read Aux Ctrl register
+ ORR r0, r0, #0x01 ; Set the FW bit (bit 0)
+ MCR p15, 0, r0, c1, c0, 1 ; Write Aux Ctrl register
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT disable_maintenance_broadcast
+ ; void disable_maintenance_broadcast(void)
+ ; Disable the broadcasting of cache & TLB maintenance operations
+disable_maintenance_broadcast PROC
+ MRC p15, 0, r0, c1, c0, 1 ; Read Aux Ctrl register
+ BIC r0, r0, #0x01 ; Clear the FW bit (bit 0)
+ MCR p15, 0, r0, c1, c0, 1 ; Write Aux Ctrl register
+
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+
+ EXPORT secure_SCU_invalidate
+ ; void secure_SCU_invalidate(unsigned int cpu, unsigned int ways)
+ ; cpu: 0x0=CPU 0 0x1=CPU 1 etc...
+ ; This function invalidates the SCU copy of the tag rams
+ ; for the specified core. Typically only done at start-up.
+ ; Possible flow:
+ ; - Invalidate L1 caches
+ ; - Invalidate SCU copy of TAG RAMs
+ ; - Join SMP
+secure_SCU_invalidate PROC
+ AND r0, r0, #0x03 ; Mask off unused bits of CPU ID
+ MOV r0, r0, LSL #2 ; Convert into bit offset (four bits per core)
+
+ AND r1, r1, #0x0F ; Mask off unused bits of ways
+ MOV r1, r1, LSL r0 ; Shift ways into the correct CPU field
+
+ MRC p15, 4, r2, c15, c0, 0 ; Read periph base address
+
+ STR r1, [r2, #0x0C] ; Write to SCU Invalidate All in Secure State
+
+ BX lr
+
+ ENDP
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of MP_SCU.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.c b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.c
new file mode 100644
index 00000000..70f1c840
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.c
@@ -0,0 +1,444 @@
+/* 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"
+
+#define DEMO_STACK_SIZE 1024
+#define DEMO_BYTE_POOL_SIZE 9120
+#define DEMO_BLOCK_POOL_SIZE 100
+#define DEMO_QUEUE_SIZE 100
+
+
+/* Define the ThreadX object control blocks... */
+
+TX_THREAD thread_0;
+TX_THREAD thread_1;
+TX_THREAD thread_2;
+TX_THREAD thread_3;
+TX_THREAD thread_4;
+TX_THREAD thread_5;
+TX_THREAD thread_6;
+TX_THREAD thread_7;
+TX_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
+
+
+
+int main(void)
+{
+
+ /* Enter ThreadX. */
+ tx_kernel_enter();
+
+ return 0;
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+CHAR *pointer;
+
+
+#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", first_unused_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;
+ }
+}
+
+
+#if 0
+#include <stdio.h>
+
+#include "v7.h"
+#include "MP_GIC.h"
+#include "MP_Mutexes.h"
+
+
+// compile-time control for the number of CPUs in the cluster
+#define nCPUs 4
+
+// per-thread space for each CPU for use by the Arm C libraries - will be zero-initialized on start-up
+char user_perthread_libspace[ nCPUs ][96];
+
+
+// Called by the C library to get the address of the per-thread libspace
+// Return a separate space for each CPU
+void * __user_perthread_libspace(void)
+{
+ return user_perthread_libspace[ getCPUID() ];
+}
+
+
+// Called by the C library to initialize the mutex to an unlocked state.
+// Return a nonzero value to indicate to the C library that it is being used in a multithreaded environment.
+int _mutex_initialize(mutex_t *m)
+{
+ initMutex(m);
+ return 1;
+}
+
+// Called by the C library to obtain a lock on the mutex.
+void _mutex_acquire(mutex_t *m)
+{
+ lockMutex(m);
+}
+
+// Called by the C library to release the lock on the mutex previously acquired
+void _mutex_release(mutex_t *m)
+{
+ unlockMutex(m);
+}
+
+
+/*
+The C library startup routine __rt_entry() is called after scatterloading has been performed by __scatterload().
+__rt_entry() attempts a mutex lock call-out as part of its startup. To avoid possible lock-up in systems with
+no global exclusive monitors in their memory system, rely on the local monitor provided within MPCore instead.
+The local monitor becomes active when the L1 D cache is enabled. So the L1 cache should be enabled after
+scatterloading has finished to avoid cache incoherency, but before __rt_entry() executes. This can be achieved
+by using the 'wrapper' function which enables the caches then calls the original __rt_entry().
+*/
+
+extern void $Super$$__rt_entry(void);
+
+void $Sub$$__rt_entry(void)
+{
+ enableBranchPrediction();
+ enableCaches();
+
+ $Super$$__rt_entry();
+}
+#endif
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.ld b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.ld
new file mode 100644
index 00000000..c2add4f2
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/demo_threadx.ld
@@ -0,0 +1,69 @@
+;LOAD 0x0000 0x00100000
+;{
+; STARTUP 0x0000
+; {
+; startup.o(StartUp, +FIRST)
+; * (InRoot$$Sections) ; Selects all sections that must be in a root region
+; * (+RO)
+; }
+;
+; SHARED_DATA +0x0
+; {
+; * (+RW,+ZI)
+; }
+;
+; IRQ_STACK 0x001FE000 EMPTY 0x1000 {}
+; ARM_LIB_STACKHEAP 0x001FC000 EMPTY 0x2000 {}
+;}
+;
+;
+;PAGETABLES 0x00500000 0x00100000
+;{
+; PAGETABLES 0x00500000 EMPTY 0x00100000
+; {
+; }
+;}
+
+LOAD_ROOT 0x0
+{
+ Root +0 0x10000
+ {
+ startup.o (StartUp, +FIRST) ;startup code
+ * (InRoot$$Sections) ;All library sections that must be in a root region
+
+ }
+}
+LOAD 0x48000000
+{
+ INIT +0 0x10000
+ {
+ demo_threadx.o (+RO) ; Place main() in a root region for the benefit of software breakpoints
+ }
+
+ ; increased from 32k to 64k
+ CODE +0 0x10000
+ {
+ * (+RO) ; Application code, including C library
+ }
+
+ SHARED_DATA +0 0x4000
+ {
+ * (+RW,+ZI) ; All RW and ZI Data
+ }
+ ; App heap for all CPUs
+ ARM_LIB_HEAP +0 ALIGN 8 EMPTY 0x2000 {}
+
+ ; App stacks for all CPUs - see startup.S
+ ARM_LIB_STACK +0 ALIGN 8 EMPTY 4*0x1000 {}
+
+ ; IRQ stacks for all CPUs - see startup.s
+ IRQ_STACK +0 ALIGN 8 EMPTY 4*256 {}
+
+}
+
+PAGETABLES 0x00500000 0x00100000
+{
+ PAGETABLES 0x00500000 EMPTY 0x00100000
+ {
+ }
+}
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/retarget.c b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/retarget.c
new file mode 100644
index 00000000..9d3c2cdc
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/retarget.c
@@ -0,0 +1,11 @@
+// Copyright ARM Ltd 2009. All rights reserved.
+
+extern void $Super$$main(void);
+extern void enable_caches(void);
+
+void $Sub$$main(void)
+{
+ enable_caches(); // enables caches
+ $Super$$main(); // calls original main()
+}
+
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/startup.S b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/startup.S
new file mode 100644
index 00000000..58c39a90
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/startup.S
@@ -0,0 +1,610 @@
+; ------------------------------------------------------------
+; Cortex-R8 MPCore SMP Prime Number Generator Example
+;
+; Copyright (c) 2011-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.
+; ------------------------------------------------------------
+
+; MPU region defines
+
+ PRESERVE8
+
+ AREA StartUp,CODE,READONLY
+
+
+; Region size <256 bytes is unpredictable
+
+Region_256B EQU 0x07
+Region_512B EQU 0x08
+Region_1K EQU 0x09
+Region_2K EQU 0x0a
+Region_4K EQU 0x0b
+Region_8K EQU 0x0c
+Region_16K EQU 0x0d
+Region_32K EQU 0x0e
+Region_64K EQU 0x0f
+Region_128K EQU 0x10
+Region_256K EQU 0x11
+Region_512K EQU 0x12
+Region_1M EQU 0x13
+Region_2M EQU 0x14
+Region_4M EQU 0x15
+Region_8M EQU 0x16
+Region_16M EQU 0x17
+Region_32M EQU 0x18
+Region_64M EQU 0x19
+Region_128M EQU 0x1a
+Region_256M EQU 0x1b
+Region_512M EQU 0x1c
+Region_1G EQU 0x1d
+Region_2G EQU 0x1e
+Region_4G EQU 0x1f
+
+Region_Enable EQU 0x01
+Execute_Never EQU 0x1000
+
+Normal_nShared EQU 0x03 ; Outer and Inner write-back, no write-allocate
+Device_Shared EQU (0x0<<0x3 :OR: 0x1)
+Device_nShared EQU 0x10
+
+Full_Access EQU 0x03
+Read_Only EQU 0x06
+
+Shared EQU 0x04
+
+
+; Standard definitions of mode bits and interrupt (I&F) flags in PSRs
+
+Mode_USR EQU 0x10
+Mode_FIQ EQU 0x11
+Mode_IRQ EQU 0x12
+Mode_SVC EQU 0x13
+Mode_ABT EQU 0x17
+Mode_UND EQU 0x1B
+Mode_SYS EQU 0x1F
+
+I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
+F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
+
+
+; ------------------------------------------------------------
+; Porting defines
+; ------------------------------------------------------------
+
+L1_COHERENT EQU 0x00014c06 ; Template descriptor for coherent memory
+L1_NONCOHERENT EQU 0x00000c1e ; Template descriptor for non-coherent memory
+L1_DEVICE EQU 0x00000c16 ; Template descriptor for device memory
+
+; ------------------------------------------------------------
+
+ ENTRY
+
+ EXPORT Vectors
+
+Vectors
+ B Reset_Handler
+ B Undefined_Handler
+ B SVC_Handler
+ B Prefetch_Handler
+ B Abort_Handler
+ B . ;Reserved vector
+ B IRQ_Handler
+ B FIQ_Handler
+
+; ------------------------------------------------------------
+; Handlers for unused exceptions
+; ------------------------------------------------------------
+
+Undefined_Handler
+ B Undefined_Handler
+SVC_Handler
+ B SVC_Handler
+Prefetch_Handler
+ B Prefetch_Handler
+Abort_Handler
+ B Abort_Handler
+FIQ_Handler
+ B FIQ_Handler
+
+; ------------------------------------------------------------
+; Imports
+; ------------------------------------------------------------
+
+ IMPORT read_irq_ack
+ IMPORT write_end_of_irq
+ IMPORT enable_GIC
+ IMPORT enable_gic_processor_interface
+ IMPORT set_priority_mask
+ IMPORT enable_irq_id
+ IMPORT set_irq_priority
+ IMPORT enable_scu
+ IMPORT join_smp
+ IMPORT secure_SCU_invalidate
+ IMPORT enable_maintenance_broadcast
+ IMPORT init_private_timer
+ IMPORT start_private_timer
+ IMPORT clear_private_timer_irq
+ IMPORT __main
+
+ IMPORT __use_two_region_memory
+ IMPORT ||Image$$IRQ_STACK$$ZI$$Limit||
+
+; [EL Change Start]
+ IMPORT _tx_thread_smp_initialize_wait
+ IMPORT _tx_thread_smp_release_cores_flag
+ IMPORT _tx_thread_context_save
+ IMPORT _tx_thread_context_restore
+ IMPORT _tx_timer_interrupt
+ IMPORT _tx_thread_smp_inter_core_interrupts
+; [EL Change End]
+
+
+; ------------------------------------------------------------
+; Interrupt Handler
+; ------------------------------------------------------------
+
+ EXPORT IRQ_Handler
+ EXPORT __tx_irq_processing_return
+IRQ_Handler PROC
+; [EL Change Start]
+; SUB lr, lr, #4 ; Pre-adjust lr
+; SRSFD sp!, #Mode_IRQ ; Save lr and SPRS to IRQ mode stack
+; PUSH {r0-r4, r12} ; Sace APCS corruptable registers to IRQ mode stack (and maintain 8 byte alignment)
+;
+; /* Jump to context save to save system context. */
+ B _tx_thread_context_save
+__tx_irq_processing_return
+ PUSH {r4, r5} ; Save some preserved registers (r5 is saved just for 8-byte alignment)
+; [EL Change End]
+
+ ; Acknowledge the interrupt
+ BL read_irq_ack
+ MOV r4, r0
+
+ ;
+ ; This example only uses (and enables) one. At this point
+ ; you would normally check the ID, and clear the source.
+ ;
+
+ ;
+ ; Additonal code to handler private timer interrupt on CPU0
+ ;
+
+ CMP r0, #29 ; If not Private Timer interrupt (ID 29), by pass
+ BNE by_pass
+
+; [EL Change Start]
+; MOV r0, #0x04 ; Code for SYS_WRITE0
+; LDR r1, =irq_handler_message0
+; SVC 0x123456
+; [EL Change End]
+
+ ; Clear timer interrupt
+ BL clear_private_timer_irq
+ DSB
+; [EL Change Start]
+ BL _tx_timer_interrupt ; Timer interrupt handler
+; [EL Change End]
+
+ B by_pass2
+
+by_pass
+
+; [EL Change Start]
+ ;
+ ; Additional code to handle SGI on CPU0
+ ;
+;
+; MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+; ANDS r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+; BNE by_pass2
+;
+; MOV r0, #0x04 ; Code for SYS_WRITE0
+; LDR r1, =irq_handler_message1
+; SVC 0x123456
+;
+; /* Just increment the per-thread interrupt count for analysis purposes. */
+;
+ MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+ AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+ LSL r0, r0, #2 ; Build offset to array indexes
+ LDR r1,=_tx_thread_smp_inter_core_interrupts ; Pickup base address of core interrupt counter array
+ ADD r1, r1, r0 ; Build array index
+ LDR r0, [r1] ; Pickup counter
+ ADD r0, r0, #1 ; Increment counter
+ STR r0, [r1] ; Store back counter
+;
+; [EL Change End]
+
+
+by_pass2
+ ; Write end of interrupt reg
+ MOV r0, r4
+ BL write_end_of_irq
+
+; [EL Change Start]
+
+;
+; /* Jump to context restore to restore system context. */
+ POP {r4, r5} ; Recover preserved registers
+ B _tx_thread_context_restore
+
+; POP {r0-r4, r12} ; Restore stacked APCS registers
+; MOV r2, #0x01 ; Set r2 so CPU leaves holding pen
+; RFEFD sp! ; Return from exception
+; [EL Change End]
+
+ ENDP
+
+
+; ------------------------------------------------------------
+; Reset Handler - Generic initialization, run by all CPUs
+; ------------------------------------------------------------
+
+ IMPORT ||Image$$IRQ_STACK$$ZI$$Limit||
+ IMPORT ||Image$$ARM_LIB_STACK$$ZI$$Limit||
+ IMPORT enable_branch_prediction
+ IMPORT invalidate_caches
+
+ EXPORT Reset_Handler ; Exported for callgraph purposes!
+Reset_Handler PROC
+
+;----------------------------------------------------------------
+; Disable MPU and caches
+;----------------------------------------------------------------
+
+; Disable MPU and cache in case it was left enabled from an earlier run
+; This does not need to be done from a cold reset
+
+ MRC p15, 0, r0, c1, c0, 0 ; Read System Control Register
+ BIC r0, r0, #0x05 ; Disable MPU (M bit) and data cache (C bit)
+ BIC r0, r0, #0x800 ; Disable branch prediction (Z bit)
+ BIC r0, r0, #0x1000 ; Disable instruction cache (I bit)
+ DSB ; Ensure all previous loads/stores have completed
+ MCR p15, 0, r0, c1, c0, 0 ; Write System Control Register
+ ISB ; Ensure subsequent insts execute wrt new MPU settings
+
+; [EL Change Start]
+ ;
+ ; Setup stacks
+ ;---------------
+;; MSR CPSR_c, #Mode_IRQ :OR: I_Bit :OR: F_Bit
+;; LDR sp, =||Image$$IRQ_STACK$$ZI$$Limit||
+;
+;; MSR CPSR_c, #Mode_SYS :OR: I_Bit :OR :F_Bit ; No interrupts
+;; LDR sp, =||Image$$ARM_LIB_STACK$$ZI$$Limit||
+
+ MSR CPSR_c, #Mode_IRQ :OR: I_Bit :OR: F_Bit
+ LDR sp, =||Image$$IRQ_STACK$$ZI$$Limit||
+
+ MSR CPSR_c, #Mode_SVC :OR: I_Bit :OR: F_Bit ; No interrupts
+ LDR sp, =||Image$$ARM_LIB_STACK$$ZI$$Limit||
+
+ MRC p15, 0, r1, c0, c0, 5 ; Read Multiprocessor Affinity Register
+ ANDS r1, r1, #0x03 ; Mask off, leaving the CPU ID field
+ CMP r1,#0 ; Is it core 0?
+ BEQ _stacks_setup ;
+_core_1
+ MSR CPSR_c, #Mode_IRQ :OR: I_Bit :OR: F_Bit
+ MOV r1, #0x800
+ SUB sp, sp, r1
+
+ MSR CPSR_c, #Mode_SVC :OR: I_Bit :OR: F_Bit ; No interrupts
+ MOV r1, #0x1000
+ SUB sp, sp, r1
+_stacks_setup
+; [EL Change End]
+
+ ;
+ ; Invalidate caches
+ ; ------------------
+ BL invalidate_caches
+
+
+ ; Clear Branch Prediction Array
+ ; ------------------------------
+ MOV r0, #0x0
+ MCR p15, 0, r0, c7, c5, 6 ; BPIALL - Invalidate entire branch predictor array
+
+
+ ;
+ ; Activate VFP/NEON, if required
+ ;-------------------------------
+
+ IF {TARGET_FPU_VFP} = {TRUE}
+
+ ; Enable access to NEON/VFP by enabling access to Coprocessors 10 and 11.
+ ; Enables Full Access i.e. in both privileged and non privileged modes
+ MRC p15, 0, r0, c1, c0, 2 ; Read Coprocessor Access Control Register (CPACR)
+ ORR r0, r0, #(0xF << 20) ; Enable access to CP 10 & 11
+ MCR p15, 0, r0, c1, c0, 2 ; Write Coprocessor Access Control Register (CPACR)
+ ISB
+
+ ; Switch on the VFP and NEON hardware
+ MOV r0, #0x40000000
+ VMSR FPEXC, r0 ; Write FPEXC register, EN bit set
+
+ ENDIF
+
+; [EL Change Start] - we don't use the MPU
+ ;BL configMPU
+; [EL Change End]
+
+ ;
+ ; SMP initialization
+ ; -------------------
+ MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+ ANDS r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+ BEQ primaryCPUInit
+ BNE secondaryCPUsInit
+
+ ENDP
+
+
+;----------------------------------------------------------------
+; MPU Configuration
+;----------------------------------------------------------------
+
+ ; Notes:
+ ; * Regions apply to both instruction and data accesses.
+ ; * Each region base address must be a multiple of its size
+ ; * Any address range not covered by an enabled region will abort
+ ; * The region at 0x0 over the Vector table is needed to support semihosting
+
+ ; Region 0: Init Base = 0x48000000 Size = 64KB Normal Non-shared Full access Executable
+ ; Region 1: Code Base = 0x48010000 Size = 32KB Normal Non-shared Full access Executable
+ ; Region 1: Data Base = 0x48018000 Size = 16KB Normal Non-shared Full access Not Executable
+ ; Region 2: Stack/Heap Base = 0x4801C000 Size = 8KB Normal Non-shared Full access Not Executable
+ ; Region 4: Vectors Base = 0x0000 Size = 64KB Normal Nonshared Full access Executable
+ ; Region 5: GIC Base = 0xAE000000 Size = 8KB Device shared Full access Not Executable
+
+ EXPORT
+configMPU PROC
+
+ MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+ ANDS r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+ ; Import linker symbols to get region base addresses
+ IMPORT ||Image$$INIT$$Base||
+ IMPORT ||Image$$CODE$$Base||
+ IMPORT ||Image$$SHARED_DATA$$Base||
+ IMPORT ||Image$$ARM_LIB_STACK$$Base||
+
+ ;; Region 0 - Init
+ MOV r1, #0
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =||Image$$INIT$$Base||
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_64K << 1) :OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR: Normal_nShared
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+ ; Region 1 - Code
+ ADD r1, r1, #1
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =||Image$$CODE$$Base||
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_64K << 1) :OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR: Normal_nShared
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+ ; Region 2 - Data
+ ADD r1, r1, #1
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =||Image$$SHARED_DATA$$Base||
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_16K << 1) :OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR: Normal_nShared :OR: Execute_Never
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+ ; Region 3 - Stack/heap
+ ADD r1, r1, #1
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =||Image$$ARM_LIB_STACK$$Base||
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_16K << 1) :OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR: Normal_nShared :OR: Execute_Never
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+ ; Region 4 - Vectors
+ ADD r1, r1, #1
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =0
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_64K << 1) :OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR:Normal_nShared :OR: Shared
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+ ; Region 5 - GIC
+ ADD r1, r1, #1
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register
+ ISB ; Ensure subsequent insts execute wrt this region
+ LDR r2, =0xAE000000
+ MCR p15, 0, r2, c6, c1, 0 ; Set region base address register
+ LDR r2, =0x0 :OR: (Region_8K << 1):OR: Region_Enable
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register
+ LDR r2, =0x0 :OR: (Full_Access << 8) :OR: Device_Shared :OR: Execute_Never
+ MCR p15, 0, r2, c6, c1, 4 ; Set region access control register
+
+
+ ; Disable all higher priority regions (assumes unified regions, which is always true for Cortex-R8)
+ MRC p15, 0, r0, c0, c0, 4 ; Read MPU Type register (MPUIR)
+ LSR r0, r0, #8
+ AND r0, r0, #0xff ; r0 = Number of MPU regions (12, 16, 20, or 24 for Cortex-R8)
+ MOV r2, #0 ; Value to write to disable region
+region_loop
+ ADD r1, r1, #1
+ CMP r0, r1
+ BLS regions_done
+ MCR p15, 0, r1, c6, c2, 0 ; Set memory region number register (RGNR)
+ MCR p15, 0, r2, c6, c1, 2 ; Set region size & enable register (DRSR)
+ B region_loop
+regions_done
+ BX lr
+
+ ENDP
+
+; ------------------------------------------------------------
+; Initialization for PRIMARY CPU
+; ------------------------------------------------------------
+
+ EXPORT primaryCPUInit
+primaryCPUInit PROC
+
+ ; Enable the SCU
+ ; ---------------
+ BL enable_scu
+
+ ;
+ ; Join SMP
+ ; ---------
+ MOV r0, #0x0 ; Move CPU ID into r0
+ MOV r1, #0xF ; Move 0xF (represents all four ways) into r1
+ BL join_smp
+
+ ;
+ ; GIC Init
+ ; ---------
+ BL enable_GIC
+ BL enable_gic_processor_interface
+
+; [EL Change Start]
+; /* Leave MPU disabled */
+; ; Enable MPU
+; ; -----------
+; ; Leave the caches disabled until after scatter loading.
+; MRC p15, 0, r0, c1, c0, 0 ; Read System Control Register
+; ORR r0, r0, #0x1 ; Set M bit 0 to enable MMU before scatter loading
+; MCR p15, 0, r0, c1, c0, 0 ; Write System Control Register
+
+ ;
+ ; Enable Private Timer for periodic IRQ
+ ; --------------------------------------
+ MOV r0, #0x1F
+ BL set_priority_mask ; Set priority mask (local)
+
+ ; [EL] Change start - don't enable interrupts here!
+ ;CPSIE i ; Clear CPSR I bit
+ ; [EL] Change end
+
+ ; Enable the Private Timer Interrupt Source
+ MOV r0, #29
+ MOV r1, #0
+ BL enable_irq_id
+
+ ; Set the priority
+ MOV r0, #29
+ MOV r1, #0
+ BL set_irq_priority
+
+ ; Configure Timer
+ MOV r0, #0xF0000
+ MOV r1, #0x0
+ BL init_private_timer
+ BL start_private_timer
+
+ ;
+ ; Enable receipt of SGI 0
+ ; ------------------------
+ MOV r0, #0x0 ; ID
+ BL enable_irq_id
+
+ MOV r0, #0x0 ; ID
+ MOV r1, #0x0 ; Priority
+ BL set_irq_priority
+; [EL Change End]
+
+ ;
+ ; Branch to C lib code
+ ; ----------------------
+ B __main
+
+ ENDP
+
+
+
+; ------------------------------------------------------------
+; Initialization for SECONDARY CPUs
+; ------------------------------------------------------------
+
+ EXPORT secondaryCPUsInit
+secondaryCPUsInit PROC
+
+; [EL Change Start] - Don't configure MPU
+ ;BL configMPU
+; [EL Change End]
+
+ ;
+ ; GIC Init
+ ; ---------
+ BL enable_gic_processor_interface
+
+ MOV r0, #0x1F ; Priority
+ BL set_priority_mask
+
+ MOV r0, #0x0 ; ID
+ BL enable_irq_id
+
+ MOV r0, #0x0 ; ID
+ MOV r1, #0x0 ; Priority
+ BL set_irq_priority
+
+ ;
+ ; Join SMP
+ ; ---------
+ MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register
+ ANDS r0, r0, #0x03 ; Mask off, leaving the CPU ID field
+ MOV r1, #0xF ; Move 0xF (represents all four ways) into r1
+ BL secure_SCU_invalidate
+
+ BL join_smp
+ BL enable_maintenance_broadcast
+
+; [EL Change Start]
+; /* Leave MPU disabled */
+; ; Enable MPU
+; ; -----------
+; ; Leave the caches disabled until after scatter loading.
+; MRC p15, 0, r0, c1, c0, 0 ; Read System Control Register
+; ORR r0, r0, #0x1 ; Set M bit 0 to enable MMU before scatter loading
+; MCR p15, 0, r0, c1, c0, 0 ; Write System Control Register
+; ISB
+
+ ;
+ ; Holding Pen
+ ; ------------
+; MOV r2, #0x00 ; Clear r2
+; CPSIE i ; Enable interrupts
+;holding_pen
+; CMP r2, #0x0 ; r2 will be set to 0x1 by IRQ handler on receiving SGI
+; WFIEQ
+; BEQ holding_pen
+; CPSID i ; IRQs not used in reset of example, so mask out interrupts
+;skip
+;
+ ;
+ ; Branch to C lib code
+ ; ----------------------
+; B __main
+
+ B _tx_thread_smp_initialize_wait
+; [EL Change End]
+
+ ENDP
+
+ END
+
+; ------------------------------------------------------------
+; End of startup.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.S b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.S
new file mode 100644
index 00000000..dfd65a2c
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.S
@@ -0,0 +1,381 @@
+; ------------------------------------------------------------
+; v7 Cache and Branch Prediction Maintenance Operations
+; ------------------------------------------------------------
+
+ PRESERVE8
+
+ AREA v7CacheOpp,CODE,READONLY
+
+; ------------------------------------------------------------
+; Cache Maintenance
+; ------------------------------------------------------------
+
+ EXPORT enable_caches
+ ; void enable_caches(void);
+enable_caches PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read System Control Register configuration data
+ ORR r0, r0, #(1 << 2) ; Set C bit
+ ORR r0, r0, #(1 << 12) ; Set I bit
+ MCR p15, 0, r0, c1, c0, 0 ; Write System Control Register configuration data
+ BX lr
+ ENDP
+
+
+ EXPORT disable_caches
+ ; void disable_caches(void)
+disable_caches PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read System Control Register configuration data
+ BIC r0, r0, #(1 << 2) ; Clear C bit
+ BIC r0, r0, #(1 << 12) ; Clear I bit
+ MCR p15, 0, r0, c1, c0, 0 ; Write System Control Register configuration data
+ BX lr
+ ENDP
+
+
+ EXPORT clean_dcache
+ ; void clean_dcache(void);
+clean_dcache PROC
+ PUSH {r4-r12}
+
+ ;
+ ; Based on code example given in section 11.2.4 of ARM DDI 0406B
+ ;
+
+ MRC p15, 1, r0, c0, c0, 1 ; Read CLIDR
+ ANDS r3, r0, #&7000000
+ MOV r3, r3, LSR #23 ; Cache level value (naturally aligned)
+ BEQ clean_dcache_finished
+ MOV r10, #0
+
+clean_dcache_loop1
+ ADD r2, r10, r10, LSR #1 ; Work out 3xcachelevel
+ MOV r1, r0, LSR r2 ; bottom 3 bits are the Cache type for this level
+ AND r1, r1, #7 ; get those 3 bits alone
+ CMP r1, #2
+ BLT clean_dcache_skip ; no cache or only instruction cache at this level
+ MCR p15, 2, r10, c0, c0, 0 ; write the Cache Size selection register
+ ISB ; ISB to sync the change to the CacheSizeID reg
+ MRC p15, 1, r1, c0, c0, 0 ; reads current Cache Size ID register
+ AND r2, r1, #&7 ; extract the line length field
+ ADD r2, r2, #4 ; add 4 for the line length offset (log2 16 bytes)
+ LDR r4, =0x3FF
+ ANDS r4, r4, r1, LSR #3 ; R4 is the max number on the way size (right aligned)
+ CLZ r5, r4 ; R5 is the bit position of the way size increment
+ LDR r7, =0x00007FFF
+ ANDS r7, r7, r1, LSR #13 ; R7 is the max number of the index size (right aligned)
+
+clean_dcache_loop2
+ MOV r9, R4 ; R9 working copy of the max way size (right aligned)
+
+clean_dcache_loop3
+ ORR r11, r10, r9, LSL r5 ; factor in the way number and cache number into R11
+ ORR r11, r11, r7, LSL r2 ; factor in the index number
+ MCR p15, 0, r11, c7, c10, 2 ; DCCSW - clean by set/way
+ SUBS r9, r9, #1 ; decrement the way number
+ BGE clean_dcache_loop3
+ SUBS r7, r7, #1 ; decrement the index
+ BGE clean_dcache_loop2
+
+clean_dcache_skip
+ ADD r10, r10, #2 ; increment the cache number
+ CMP r3, r10
+ BGT clean_dcache_loop1
+
+clean_dcache_finished
+ POP {r4-r12}
+
+ BX lr
+ ENDP
+
+ EXPORT clean_invalidate_dcache
+ ; void clean_invalidate_dcache(void);
+clean_invalidate_dcache PROC
+ PUSH {r4-r12}
+
+ ;
+ ; Based on code example given in section 11.2.4 of ARM DDI 0406B
+ ;
+
+ MRC p15, 1, r0, c0, c0, 1 ; Read CLIDR
+ ANDS r3, r0, #&7000000
+ MOV r3, r3, LSR #23 ; Cache level value (naturally aligned)
+ BEQ clean_invalidate_dcache_finished
+ MOV r10, #0
+
+clean_invalidate_dcache_loop1
+ ADD r2, r10, r10, LSR #1 ; Work out 3xcachelevel
+ MOV r1, r0, LSR r2 ; bottom 3 bits are the Cache type for this level
+ AND r1, r1, #7 ; get those 3 bits alone
+ CMP r1, #2
+ BLT clean_invalidate_dcache_skip ; no cache or only instruction cache at this level
+ MCR p15, 2, r10, c0, c0, 0 ; write the Cache Size selection register
+ ISB ; ISB to sync the change to the CacheSizeID reg
+ MRC p15, 1, r1, c0, c0, 0 ; reads current Cache Size ID register
+ AND r2, r1, #&7 ; extract the line length field
+ ADD r2, r2, #4 ; add 4 for the line length offset (log2 16 bytes)
+ LDR r4, =0x3FF
+ ANDS r4, r4, r1, LSR #3 ; R4 is the max number on the way size (right aligned)
+ CLZ r5, r4 ; R5 is the bit position of the way size increment
+ LDR r7, =0x00007FFF
+ ANDS r7, r7, r1, LSR #13 ; R7 is the max number of the index size (right aligned)
+
+clean_invalidate_dcache_loop2
+ MOV r9, R4 ; R9 working copy of the max way size (right aligned)
+
+clean_invalidate_dcache_loop3
+ ORR r11, r10, r9, LSL r5 ; factor in the way number and cache number into R11
+ ORR r11, r11, r7, LSL r2 ; factor in the index number
+ MCR p15, 0, r11, c7, c14, 2 ; DCCISW - clean and invalidate by set/way
+ SUBS r9, r9, #1 ; decrement the way number
+ BGE clean_invalidate_dcache_loop3
+ SUBS r7, r7, #1 ; decrement the index
+ BGE clean_invalidate_dcache_loop2
+
+clean_invalidate_dcache_skip
+ ADD r10, r10, #2 ; increment the cache number
+ CMP r3, r10
+ BGT clean_invalidate_dcache_loop1
+
+clean_invalidate_dcache_finished
+ POP {r4-r12}
+
+ BX lr
+ ENDP
+
+
+ EXPORT invalidate_caches
+ ; void invalidate_caches(void);
+invalidate_caches PROC
+ PUSH {r4-r12}
+
+ ;
+ ; Based on code example given in section B2.2.4/11.2.4 of ARM DDI 0406B
+ ;
+
+ MOV r0, #0
+ MCR p15, 0, r0, c7, c5, 0 ; ICIALLU - Invalidate entire I Cache, and flushes branch target cache
+
+ MRC p15, 1, r0, c0, c0, 1 ; Read CLIDR
+ ANDS r3, r0, #&7000000
+ MOV r3, r3, LSR #23 ; Cache level value (naturally aligned)
+ BEQ invalidate_caches_finished
+ MOV r10, #0
+
+invalidate_caches_loop1
+ ADD r2, r10, r10, LSR #1 ; Work out 3xcachelevel
+ MOV r1, r0, LSR r2 ; bottom 3 bits are the Cache type for this level
+ AND r1, r1, #7 ; get those 3 bits alone
+ CMP r1, #2
+ BLT invalidate_caches_skip ; no cache or only instruction cache at this level
+ MCR p15, 2, r10, c0, c0, 0 ; write the Cache Size selection register
+ ISB ; ISB to sync the change to the CacheSizeID reg
+ MRC p15, 1, r1, c0, c0, 0 ; reads current Cache Size ID register
+ AND r2, r1, #&7 ; extract the line length field
+ ADD r2, r2, #4 ; add 4 for the line length offset (log2 16 bytes)
+ LDR r4, =0x3FF
+ ANDS r4, r4, r1, LSR #3 ; R4 is the max number on the way size (right aligned)
+ CLZ r5, r4 ; R5 is the bit position of the way size increment
+ LDR r7, =0x00007FFF
+ ANDS r7, r7, r1, LSR #13 ; R7 is the max number of the index size (right aligned)
+
+invalidate_caches_loop2
+ MOV r9, R4 ; R9 working copy of the max way size (right aligned)
+
+invalidate_caches_loop3
+ ORR r11, r10, r9, LSL r5 ; factor in the way number and cache number into R11
+ ORR r11, r11, r7, LSL r2 ; factor in the index number
+ MCR p15, 0, r11, c7, c6, 2 ; DCISW - invalidate by set/way
+ SUBS r9, r9, #1 ; decrement the way number
+ BGE invalidate_caches_loop3
+ SUBS r7, r7, #1 ; decrement the index
+ BGE invalidate_caches_loop2
+
+invalidate_caches_skip
+ ADD r10, r10, #2 ; increment the cache number
+ CMP r3, r10
+ BGT invalidate_caches_loop1
+
+invalidate_caches_finished
+ POP {r4-r12}
+ BX lr
+ ENDP
+
+
+ EXPORT invalidate_caches_is
+ ; void invalidate_caches_is(void);
+invalidate_caches_is PROC
+ PUSH {r4-r12}
+
+ MOV r0, #0
+ MCR p15, 0, r0, c7, c1, 0 ; ICIALLUIS - Invalidate entire I Cache inner shareable
+
+ MRC p15, 1, r0, c0, c0, 1 ; Read CLIDR
+ ANDS r3, r0, #&7000000
+ MOV r3, r3, LSR #23 ; Cache level value (naturally aligned)
+ BEQ invalidate_caches_is_finished
+ MOV r10, #0
+
+invalidate_caches_is_loop1
+ ADD r2, r10, r10, LSR #1 ; Work out 3xcachelevel
+ MOV r1, r0, LSR r2 ; bottom 3 bits are the Cache type for this level
+ AND r1, r1, #7 ; get those 3 bits alone
+ CMP r1, #2
+ BLT invalidate_caches_is_skip ; no cache or only instruction cache at this level
+ MCR p15, 2, r10, c0, c0, 0 ; write the Cache Size selection register
+ ISB ; ISB to sync the change to the CacheSizeID reg
+ MRC p15, 1, r1, c0, c0, 0 ; reads current Cache Size ID register
+ AND r2, r1, #&7 ; extract the line length field
+ ADD r2, r2, #4 ; add 4 for the line length offset (log2 16 bytes)
+ LDR r4, =0x3FF
+ ANDS r4, r4, r1, LSR #3 ; R4 is the max number on the way size (right aligned)
+ CLZ r5, r4 ; R5 is the bit position of the way size increment
+ LDR r7, =0x00007FFF
+ ANDS r7, r7, r1, LSR #13 ; R7 is the max number of the index size (right aligned)
+
+invalidate_caches_is_loop2
+ MOV r9, R4 ; R9 working copy of the max way size (right aligned)
+
+invalidate_caches_is_loop3
+ ORR r11, r10, r9, LSL r5 ; factor in the way number and cache number into R11
+ ORR r11, r11, r7, LSL r2 ; factor in the index number
+ MCR p15, 0, r11, c7, c6, 2 ; DCISW - clean by set/way
+ SUBS r9, r9, #1 ; decrement the way number
+ BGE invalidate_caches_is_loop3
+ SUBS r7, r7, #1 ; decrement the index
+ BGE invalidate_caches_is_loop2
+
+invalidate_caches_is_skip
+ ADD r10, r10, #2 ; increment the cache number
+ CMP r3, r10
+ BGT invalidate_caches_is_loop1
+
+invalidate_caches_is_finished
+ POP {r4-r12}
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; TLB
+; ------------------------------------------------------------
+
+ EXPORT invalidate_unified_tlb
+ ; void invalidate_unified_tlb(void);
+invalidate_unified_tlb PROC
+ MOV r0, #1
+ MCR p15, 0, r0, c8, c7, 0 ; TLBIALL - Invalidate entire unified TLB
+ BX lr
+ ENDP
+
+ EXPORT invalidate_unified_tlb_is
+ ; void invalidate_unified_tlb_is(void);
+invalidate_unified_tlb_is PROC
+ MOV r0, #1
+ MCR p15, 0, r0, c8, c3, 0 ; TLBIALLIS - Invalidate entire unified TLB Inner Shareable
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; Branch Prediction
+; ------------------------------------------------------------
+
+ EXPORT enable_branch_prediction
+ ; void enable_branch_prediction(void)
+enable_branch_prediction PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read SCTLR
+ ORR r0, r0, #(1 << 11) ; Set the Z bit (bit 11)
+ MCR p15, 0,r0, c1, c0, 0 ; Write SCTLR
+ BX lr
+ ENDP
+
+ EXPORT disable_branch_prediction
+ ; void disable_branch_prediction(void)
+disable_branch_prediction PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read SCTLR
+ BIC r0, r0, #(1 << 11) ; Clear the Z bit (bit 11)
+ MCR p15, 0,r0, c1, c0, 0 ; Write SCTLR
+ BX lr
+ ENDP
+
+ EXPORT invalidate_branch_target_cache
+ ; void invalidate_branch_target_cache(void)
+invalidate_branch_target_cache PROC
+ MOV r0, #0
+ MCR p15, 0, r0, c7, c5, 6 ; BPIALL - Invalidate entire branch predictor array
+ BX lr
+ ENDP
+
+ EXPORT invalidate_branch_target_cache_is
+ ; void invalidate_branch_target_cache_is(void)
+invalidate_branch_target_cache_is PROC
+ MOV r0, #0
+ MCR p15, 0, r0, c7, c1, 6 ; BPIALLIS - Invalidate entire branch predictor array Inner Shareable
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; High Vecs
+; ------------------------------------------------------------
+
+ EXPORT enable_highvecs
+ ; void enable_highvecs(void);
+enable_highvecs PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read Control Register
+ ORR r0, r0, #(1 << 13) ; Set the V bit (bit 13)
+ MCR p15, 0, r0, c1, c0, 0 ; Write Control Register
+ BX lr
+ ENDP
+
+ EXPORT disable_highvecs
+ ; void disable_highvecs(void);
+disable_highvecs PROC
+ MRC p15, 0, r0, c1, c0, 0 ; Read Control Register
+ BIC r0, r0, #(1 << 13) ; Clear the V bit (bit 13)
+ MCR p15, 0, r0, c1, c0, 0 ; Write Control Register
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; Context ID
+; ------------------------------------------------------------
+
+ EXPORT get_context_id
+ ; uint32_t get_context_id(void);
+get_context_id PROC
+ MRC p15, 0, r0, c13, c0, 1 ; Read Context ID Register
+ BX lr
+ ENDP
+
+ EXPORT set_context_id
+ ; void set_context_id(uint32_t);
+set_context_id PROC
+ MCR p15, 0, r0, c13, c0, 1 ; Write Context ID Register
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; ID registers
+; ------------------------------------------------------------
+
+ EXPORT get_MIDR
+ ; uint32_t get_MIDR(void);
+get_MIDR PROC
+ MRC p15, 0, r0, c0, c0, 0 ; Read Main ID Register (MIDR)
+ BX lr
+ ENDP
+
+ EXPORT get_MPIDR
+ ; uint32_t get_MPIDR(void);
+get_MPIDR PROC
+ MRC p15, 0, r0, c0 ,c0, 5; Read Multiprocessor ID register (MPIDR)
+ BX lr
+ ENDP
+
+; ------------------------------------------------------------
+; End of code
+; ------------------------------------------------------------
+
+ END
+
+; ------------------------------------------------------------
+; End of v7.s
+; ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.h b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.h
new file mode 100644
index 00000000..52a3c679
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/sample_threadx/v7.h
@@ -0,0 +1,117 @@
+// ------------------------------------------------------------
+// v7-A Cache, TLB and Branch Prediction Maintenance Operations
+// Header File
+//
+// Copyright ARM Ltd 2009. All rights reserved.
+// ------------------------------------------------------------
+
+#ifndef _SEE_V7_h
+#define _SEE_V7_h
+
+#include "kernel.h"
+
+//
+// Note:
+// *_is() stands for "inner shareable"
+//
+
+// ------------------------------------------------------------
+// Caches
+
+void enable_caches(void);
+void disable_caches(void);
+
+void clean_dcache(void);
+void clean_invalidate_dcache(void);
+
+void invalidate_caches(void);
+void invalidate_caches_is(void);
+
+// ------------------------------------------------------------
+// TLBs
+
+void invalidate_unified_tlb(void);
+void invalidate_unified_tlb_is(void);
+
+// ------------------------------------------------------------
+// Branch prediction
+
+void enable_branch_prediction(void);
+void disable_branch_prediction(void);
+
+void invalidate_branch_target_cache(void);
+void invalidate_branch_target_cache_is(void);
+
+// ------------------------------------------------------------
+// High Vecs
+
+void enable_highvecs(void);
+void disable_highvecs(void);
+
+// ------------------------------------------------------------
+// ID Registers
+
+uint32_t get_MIDR(void);
+
+#define MIDR_IMPL_SHIFT 24
+#define MIDR_IMPL_MASK 0xFF
+#define MIDR_VAR_SHIFT 20
+#define MIDR_VAR_MASK 0xF
+#define MIDR_ARCH_SHIFT 16
+#define MIDR_ARCH_MASK 0xF
+#define MIDR_PART_SHIFT 4
+#define MIDR_PART_MASK 0xFFF
+#define MIDR_REV_SHIFT 0
+#define MIDR_REV_MASK 0xF
+
+// tmp = get_MIDR();
+// implementor = (tmp >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+// variant = (tmp >> MIDR_VAR_SHIFT) & MIDR_VAR_MASK;
+// architecture= (tmp >> MIDR_ARCH_SHIFT) & MIDR_ARCH_MASK;
+// part_number = (tmp >> MIDR_PART_SHIFT) & MIDR_PART_MASK;
+// revision = tmp & MIDR_REV_MASK;
+
+#define MIDR_PART_CA5 0xC05
+#define MIDR_PART_CA8 0xC08
+#define MIDR_PART_CA9 0xC09
+
+uint32_t get_MPIDR(void);
+
+#define MPIDR_FORMAT_SHIFT 31
+#define MPIDR_FORMAT_MASK 0x1
+#define MPIDR_UBIT_SHIFT 30
+#define MPIDR_UBIT_MASK 0x1
+#define MPIDR_CLUSTER_SHIFT 7
+#define MPIDR_CLUSTER_MASK 0xF
+#define MPIDR_CPUID_SHIFT 0
+#define MPIDR_CPUID_MASK 0x3
+
+#define MPIDR_CPUID_CPU0 0x0
+#define MPIDR_CPUID_CPU1 0x1
+#define MPIDR_CPUID_CPU2 0x2
+#define MPIDR_CPUID_CPU3 0x3
+
+#define MPIDR_UNIPROCESSPR 0x1
+
+#define MPDIR_NEW_FORMAT 0x1
+
+// ------------------------------------------------------------
+// Context ID
+
+uint32_t get_context_id(void);
+void set_context_id(uint32_t);
+
+#define CONTEXTID_ASID_SHIFT 0
+#define CONTEXTID_ASID_MASK 0xFF
+#define CONTEXTID_PROCID_SHIFT 8
+#define CONTEXTID_PROCID_MASK 0x00FFFFFF
+
+// tmp = get_context_id();
+// ASID = tmp & CONTEXTID_ASID_MASK;
+// PROCID = (tmp >> CONTEXTID_PROCID_SHIFT) & CONTEXTID_PROCID_MASK;
+
+#endif
+
+// ------------------------------------------------------------
+// End of v7.h
+// ------------------------------------------------------------
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/tx/.cproject b/ports_smp/cortex_r8_smp/ac5/example_build/tx/.cproject
new file mode 100644
index 00000000..5aaf33a1
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/example_build/tx/.cproject
@@ -0,0 +1,90 @@
+<?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.1507005551">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551" 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="com.arm.eclipse.builder.armcc.error" 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.1507005551" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug.base">
+ <folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.1507005551." name="/" resourcePath="">
+ <toolChain id="com.arm.toolchain.baremetal.169423023" name="Arm Compiler 5 (DS-5 built-in)" superClass="com.arm.toolchain.baremetal">
+ <option id="com.arm.toolchain.ac5.option.target.cpu_fpu.626869623" superClass="com.arm.toolchain.ac5.option.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R8.VFPv3_D16_FP16" valueType="string"/>
+ <option id="com.arm.toolchain.ac5.option.fppcs.792119847" name="Floating-point PCS" superClass="com.arm.toolchain.ac5.option.fppcs" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.toolchain.ac5.option.inst.503868103" name="Instruction set" superClass="com.arm.toolchain.ac5.option.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <targetPlatform id="com.arm.toolchain.baremetal.169423023.1240534128" name=""/>
+ <builder buildPath="${workspace_loc:/tx}/Debug" id="com.arm.toolchain.baremetal.builder.95096803" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.baremetal.builder"/>
+ <tool id="com.arm.tool.c.compiler.1278650727" name="Arm C Compiler 5" superClass="com.arm.tool.c.compiler">
+ <option defaultValue="com.arm.tool.c.compiler.option.optlevel.min" id="com.arm.tool.c.compiler.option.optlevel.186573719" name="Optimization level" superClass="com.arm.tool.c.compiler.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.targetcpu.511690441" name="Target CPU (--cpu)" superClass="com.arm.tool.c.compiler.option.targetcpu" useByScannerDiscovery="true" value="Cortex-R8" valueType="string"/>
+ <option id="com.arm.tool.c.compiler.option.fppcs.402196819" name="Floating-point PCS (--apcs)" superClass="com.arm.tool.c.compiler.option.fppcs" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.inst.66626183" name="Instruction set" superClass="com.arm.tool.c.compiler.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <option id="com.arm.tool.c.compiler.option.incpath.1434689289" superClass="com.arm.tool.c.compiler.option.incpath" 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>
+ <inputType id="com.arm.tool.c.compiler.input.1039401648" superClass="com.arm.tool.c.compiler.input"/>
+ <inputType id="com.arm.tool.cpp.compiler.input.1465176759" superClass="com.arm.tool.cpp.compiler.input"/>
+ </tool>
+ <tool id="com.arm.tool.cpp.compiler.638753534" name="Arm C++ Compiler 5" superClass="com.arm.tool.cpp.compiler">
+ <option defaultValue="com.arm.tool.c.compiler.option.optlevel.min" id="com.arm.tool.c.compiler.option.optlevel.751811346" name="Optimization level" superClass="com.arm.tool.c.compiler.option.optlevel" valueType="enumerated"/>
+ </tool>
+ <tool id="com.arm.tool.assembler.184544494" name="Arm Assembler 5" superClass="com.arm.tool.assembler">
+ <option id="com.arm.tool.assembler.option.cpu.2038506892" name="Target CPU (--cpu)" superClass="com.arm.tool.assembler.option.cpu" useByScannerDiscovery="true" value="Cortex-R8" valueType="string"/>
+ <option id="com.arm.tool.assembler.option.fppcs.1004491031" name="Floating-point PCS (--apcs)" superClass="com.arm.tool.assembler.option.fppcs" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.fppcs.hard" valueType="enumerated"/>
+ <option id="com.arm.tool.assembler.option.inst.1677679517" name="Instruction set" superClass="com.arm.tool.assembler.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.option.inst.arm" valueType="enumerated"/>
+ <option id="com.arm.tool.assembler.option.preproc.1236693733" name="Preprocess input before assembling (--cpreproc)" superClass="com.arm.tool.assembler.option.preproc" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+ <inputType id="com.arm.tool.assembler.input.1190173496" superClass="com.arm.tool.assembler.input"/>
+ </tool>
+ <tool id="com.arm.tool.c.linker.1353775702" name="Arm Linker 5" superClass="com.arm.tool.c.linker"/>
+ <tool id="com.arm.tool.librarian.888842860" name="Arm Librarian 5" superClass="com.arm.tool.librarian"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="com.arm.eclipse.build.config.v6.lib.release.base.1262125868">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.release.base.1262125868" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <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"/>
+ </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.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.release.base.1262125868" name="Release" parent="com.arm.eclipse.build.config.v6.lib.release.base">
+ <folderInfo id="com.arm.eclipse.build.config.v6.lib.release.base.1262125868." name="/" resourcePath="">
+ <toolChain id="com.arm.toolchain.v6.lib.release.base.var.arm_compiler_6-6.492969017" name="Arm Compiler 6">
+ <targetPlatform id="com.arm.toolchain.v6.lib.release.base.var.arm_compiler_6-6.492969017.371110606" name=""/>
+ <builder autoBuildTarget="all" buildPath="${workspace_loc:/tx}/Release" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.v6.builder.1194834518" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="false" superClass="com.arm.toolchain.v6.builder"/>
+ </toolChain>
+ </folderInfo>
+ </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.1408735755" 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="com.arm.projectSettings" version="6.0.0"/>
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+</cproject>
diff --git a/ports_smp/cortex_r8_smp/ac5/example_build/tx/.project b/ports_smp/cortex_r8_smp/ac5/example_build/tx/.project
new file mode 100644
index 00000000..10681969
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/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_smp/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_smp/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_smp/cortex_r8_smp/ac5/inc/tx_port.h b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h
new file mode 100644
index 00000000..1de09e88
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h
@@ -0,0 +1,412 @@
+/**************************************************************************/
+/* */
+/* 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 SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file contains data type definitions that make the ThreadX */
+/* real-time kernel function identically on a variety of different */
+/* processor architectures. For example, the size or number of bits */
+/* in an "int" data type vary between microprocessor architectures and */
+/* even C compilers for the same microprocessor. ThreadX does not */
+/* directly use native C data types. Instead, ThreadX creates its */
+/* own special types that can be mapped to actual data types by this */
+/* file to guarantee consistency in the interface and functionality. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+
+#ifndef TX_PORT_H
+#define TX_PORT_H
+
+
+/************* Define ThreadX SMP constants. *************/
+
+/* Define the ThreadX SMP maximum number of cores. */
+
+#ifndef TX_THREAD_SMP_MAX_CORES
+#define TX_THREAD_SMP_MAX_CORES 2
+#endif
+
+
+/* Define the ThreadX SMP core mask. */
+
+#ifndef TX_THREAD_SMP_CORE_MASK
+#define TX_THREAD_SMP_CORE_MASK 0x3 /* Where bit 0 represents Core 0, bit 1 represents Core 1, etc. */
+#endif
+
+
+/* Define INLINE_DECLARE to whitespace for ARM compiler. */
+
+#define INLINE_DECLARE
+
+
+/* Define dynamic number of cores option. When commented out, the number of cores is static. */
+
+/* #define TX_THREAD_SMP_DYNAMIC_CORE_MAX */
+
+
+/* Define ThreadX SMP initialization macro. */
+
+#define TX_PORT_SPECIFIC_PRE_INITIALIZATION
+
+
+/* Define ThreadX SMP pre-scheduler initialization. */
+
+#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
+
+
+/* Enable the inter-core interrupt logic. */
+
+#define TX_THREAD_SMP_INTER_CORE_INTERRUPT
+
+
+/* Determine if there is customer-specific wakeup logic needed. */
+
+#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
+
+/* Include customer-specific wakeup code. */
+
+#include "tx_thread_smp_core_wakeup.h"
+#else
+
+#ifdef TX_THREAD_SMP_DEFAULT_WAKEUP_LOGIC
+
+/* Default wakeup code. */
+#define TX_THREAD_SMP_WAKEUP_LOGIC
+#define TX_THREAD_SMP_WAKEUP(i) _tx_thread_smp_core_preempt(i)
+#endif
+#endif
+
+
+/* Ensure that the in-line resume/suspend define is not allowed. */
+
+#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
+#undef TX_INLINE_THREAD_RESUME_SUSPEND
+#endif
+
+
+/************* End ThreadX SMP constants. *************/
+
+/* 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 long LONG;
+typedef unsigned long ULONG;
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+
+/* Define the priority levels for ThreadX. Legal values range
+ from 32 to 1024 and MUST be evenly divisible by 32. */
+
+#ifndef TX_MAX_PRIORITIES
+#define TX_MAX_PRIORITIES 32
+#endif
+
+
+/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
+ thread creation is less than this value, the thread create call will return an error. */
+
+#ifndef TX_MINIMUM_STACK
+#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
+#endif
+
+
+/* Define the system timer thread's default stack size and priority. These are only applicable
+ if TX_TIMER_PROCESS_IN_ISR is not defined. */
+
+#ifndef TX_TIMER_THREAD_STACK_SIZE
+#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
+#endif
+
+#ifndef TX_TIMER_THREAD_PRIORITY
+#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
+#endif
+
+
+/* Define various constants for the ThreadX ARM port. */
+
+#ifdef TX_ENABLE_FIQ_SUPPORT
+#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */
+#else
+#define TX_INT_DISABLE 0x80 /* Disable IRQ interrupts */
+#endif
+#define TX_INT_ENABLE 0x00 /* Enable IRQ interrupts */
+
+
+/* Define the clock source for trace event entry time stamp. The following two item are port specific.
+ For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
+ source constants would be:
+
+#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
+#define TX_TRACE_TIME_MASK 0x0000FFFFUL
+
+*/
+
+#ifndef TX_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_vfp_enable;
+#define TX_THREAD_EXTENSION_3
+
+
+/* Define the port extensions of the remaining ThreadX objects. */
+
+#define TX_BLOCK_POOL_EXTENSION
+#define TX_BYTE_POOL_EXTENSION
+#define TX_EVENT_FLAGS_GROUP_EXTENSION
+#define TX_MUTEX_EXTENSION
+#define TX_QUEUE_EXTENSION
+#define TX_SEMAPHORE_EXTENSION
+#define TX_TIMER_EXTENSION
+
+
+/* Define the user extension field of the thread control block. Nothing
+ additional is needed for this port so it is defined as white space. */
+
+#ifndef TX_THREAD_USER_EXTENSION
+#define TX_THREAD_USER_EXTENSION
+#endif
+
+
+/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
+ tx_thread_shell_entry, and tx_thread_terminate. */
+
+
+#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
+#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
+#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
+#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
+
+
+/* Define the ThreadX object creation extensions for 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
+
+#ifndef __thumb
+
+#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
+ b = (ULONG) __clz((unsigned int) m); \
+ b = 31 - b;
+#endif
+#endif
+
+
+/************* Define ThreadX SMP data types and function prototypes. *************/
+
+struct TX_THREAD_STRUCT;
+
+
+/* Define the ThreadX SMP protection structure. */
+
+typedef struct TX_THREAD_SMP_PROTECT_STRUCT
+{
+ ULONG tx_thread_smp_protect_in_force;
+ struct TX_THREAD_STRUCT *
+ tx_thread_smp_protect_thread;
+ ULONG tx_thread_smp_protect_core;
+ ULONG tx_thread_smp_protect_count;
+
+ /* Implementation specific information follows. */
+
+ ULONG tx_thread_smp_protect_get_caller;
+ ULONG tx_thread_smp_protect_sr;
+ ULONG tx_thread_smp_protect_release_caller;
+} TX_THREAD_SMP_PROTECT;
+
+
+/* Define ThreadX interrupt lockout and restore macros for protection on
+ access of critical kernel information. The restore interrupt macro must
+ restore the interrupt posture of the running thread prior to the value
+ present prior to the disable macro. In most cases, the save area macro
+ is used to define a local function save area for the disable and restore
+ macros. */
+
+#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
+
+#define TX_DISABLE interrupt_save = _tx_thread_smp_protect();
+#define TX_RESTORE _tx_thread_smp_unprotect(interrupt_save);
+
+
+/************* End ThreadX SMP data type and function prototype definitions. *************/
+
+
+/* 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 VFP extension for the Cortex-A9. Each is assumed to be called in the context of the executing
+ thread. */
+
+void tx_thread_vfp_enable(void);
+void tx_thread_vfp_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 ARMv7-R SMP Version 6.2.0 *";
+#else
+extern CHAR _tx_version_id[];
+#endif
+
+
+#endif
+
+
+
+
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_initialize_low_level.s b/ports_smp/cortex_r8_smp/ac5/src/tx_initialize_low_level.s
new file mode 100644
index 00000000..86879b01
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_initialize_low_level.s
@@ -0,0 +1,99 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_stack_ptr
+ IMPORT _tx_initialize_unused_memory
+ IMPORT _tx_version_id
+ IMPORT _tx_build_options
+ IMPORT ||Image$$SHARED_DATA$$ZI$$Limit||
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_initialize_low_level SMP/Cortex-A8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for any low-level processor */
+/* initialization, including setting up interrupt vectors, setting */
+/* up a periodic timer interrupt source, saving the system stack */
+/* pointer for use in ISR processing later, and finding the first */
+/* available RAM memory address for tx_application_define. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_initialize_low_level(VOID)
+// {
+ EXPORT _tx_initialize_low_level
+_tx_initialize_low_level
+
+ /* Save the first available memory address. */
+ // _tx_initialize_unused_memory = (VOID_PTR) (||Image$$SHARED_DATA$$ZI$$Limit||);
+
+ LDR r0, =||Image$$SHARED_DATA$$ZI$$Limit|| // Get end of non-initialized RAM area
+ LDR r2, =_tx_initialize_unused_memory // Pickup unused memory ptr address
+ STR r0, [r2, #0] // Save first free memory address
+
+ /* Done, return to caller. */
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+// }
+
+ /* Reference build options and version ID to ensure they come in. */
+
+ LDR r2, =_tx_build_options // Pickup build options variable address
+ LDR r0, [r2, #0] // Pickup build options content
+ LDR r2, =_tx_version_id // Pickup version ID variable address
+ LDR r0, [r2, #0] // Pickup version ID content
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_restore.s
new file mode 100644
index 00000000..cdc575f8
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_restore.s
@@ -0,0 +1,275 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+DISABLE_INTS EQU 0xC0 // Disable IRQ & FIQ interrupts
+IRQ_MODE EQU 0xD2 // IRQ mode
+SVC_MODE EQU 0xD3 // SVC mode
+ ELSE
+DISABLE_INTS EQU 0x80 // Disable IRQ interrupts
+IRQ_MODE EQU 0x92 // IRQ mode
+SVC_MODE EQU 0x93 // SVC mode
+ ENDIF
+
+ IMPORT _tx_thread_system_state
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_execute_ptr
+ IMPORT _tx_timer_time_slice
+ IMPORT _tx_thread_schedule
+ IMPORT _tx_thread_preempt_disable
+ IMPORT _tx_timer_interrupt_active
+ IMPORT _tx_thread_smp_protection
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ IMPORT _tx_execution_isr_exit
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_restore SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_restore(VOID)
+// {
+ EXPORT _tx_thread_context_restore
+_tx_thread_context_restore
+
+ /* Lockout interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR exit function to indicate an ISR is complete. */
+
+ BL _tx_execution_isr_exit // Call the ISR exit function
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+
+ /* Determine if interrupts are nested. */
+ // if (--_tx_thread_system_state[core])
+ // {
+
+ LDR r3, =_tx_thread_system_state // Pickup address of system state var
+ ADD r3, r3, r12 // Build array offset
+ LDR r2, [r3, #0] // Pickup system state
+ SUB r2, r2, #1 // Decrement the counter
+ STR r2, [r3, #0] // Store the counter
+ CMP r2, #0 // Was this the first interrupt?
+ BEQ __tx_thread_not_nested_restore // If so, not a nested restore
+
+ /* Interrupts are nested. */
+
+ /* Just recover the saved registers and return to the point of
+ interrupt. */
+
+ LDMIA sp!, {r0, r10, r12, lr} // Recover SPSR, POI, and scratch regs
+ MSR SPSR_cxsf, r0 // Put SPSR back
+ LDMIA sp!, {r0-r3} // Recover r0-r3
+ MOVS pc, lr // Return to point of interrupt
+
+ // }
+__tx_thread_not_nested_restore
+
+ /* Determine if a thread was interrupted and no preemption is required. */
+ //else if (((_tx_thread_current_ptr[core]) && (_tx_thread_current_ptr[core] == _tx_thread_execute_ptr[core])
+ // || (_tx_thread_preempt_disable))
+ // {
+
+ LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ ADD r1, r1, r12 // Build index to this core's current thread ptr
+ LDR r0, [r1, #0] // Pickup actual current thread pointer
+ CMP r0, #0 // Is it NULL?
+ BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted
+
+ LDR r3, =_tx_thread_smp_protection // Get address of protection structure
+ LDR r2, [r3, #8] // Pickup owning core
+ CMP r2, r10 // Is the owning core the same as the protected core?
+ BNE __tx_thread_skip_preempt_check // No, skip the preempt disable check since this is only valid for the owning core
+
+ LDR r3, =_tx_thread_preempt_disable // Pickup preempt disable address
+ LDR r2, [r3, #0] // Pickup actual preempt disable flag
+ CMP r2, #0 // Is it set?
+ BNE __tx_thread_no_preempt_restore // Yes, don't preempt this thread
+__tx_thread_skip_preempt_check
+
+ LDR r3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
+ ADD r3, r3, r12 // Build index to this core's execute thread ptr
+ LDR r2, [r3, #0] // Pickup actual execute thread pointer
+ CMP r0, r2 // Is the same thread highest priority?
+ BNE __tx_thread_preempt_restore // No, preemption needs to happen
+
+__tx_thread_no_preempt_restore
+
+ /* Restore interrupted thread or ISR. */
+
+ /* Pickup the saved stack pointer. */
+ // tmp_ptr = _tx_thread_current_ptr[core] -> tx_thread_stack_ptr;
+
+ /* Recover the saved context and return to the point of interrupt. */
+
+ LDMIA sp!, {r0, r10, r12, lr} // Recover SPSR, POI, and scratch regs
+ MSR SPSR_cxsf, r0 // Put SPSR back
+ LDMIA sp!, {r0-r3} // Recover r0-r3
+ MOVS pc, lr // Return to point of interrupt
+
+ // }
+ // else
+ // {
+__tx_thread_preempt_restore
+
+ LDMIA sp!, {r3, r10, r12, lr} // Recover temporarily saved registers
+ MOV r1, lr // Save lr (point of interrupt)
+ MOV r2, #SVC_MODE // Build SVC mode CPSR
+ MSR CPSR_c, r2 // Enter SVC mode
+ STR r1, [sp, #-4]! // Save point of interrupt
+ STMDB sp!, {r4-r12, lr} // Save upper half of registers
+ MOV r4, r3 // Save SPSR in r4
+ MOV r2, #IRQ_MODE // Build IRQ mode CPSR
+ MSR CPSR_c, r2 // Enter IRQ mode
+ LDMIA sp!, {r0-r3} // Recover r0-r3
+ MOV r5, #SVC_MODE // Build SVC mode CPSR
+ MSR CPSR_c, r5 // Enter SVC mode
+ STMDB sp!, {r0-r3} // Save r0-r3 on thread's stack
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+ LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ ADD r1, r1, r12 // Build index to current thread ptr
+ LDR r0, [r1, #0] // Pickup current thread pointer
+
+ IF {TARGET_FPU_VFP} = {TRUE}
+ LDR r2, [r0, #160] // Pickup the VFP enabled flag
+ CMP r2, #0 // Is the VFP enabled?
+ BEQ _tx_skip_irq_vfp_save // No, skip VFP IRQ save
+ VMRS r2, FPSCR // Pickup the FPSCR
+ STR r2, [sp, #-4]! // Save FPSCR
+ VSTMDB sp!, {D0-D15} // Save D0-D15
+_tx_skip_irq_vfp_save
+ ENDIF
+
+ MOV r3, #1 // Build interrupt stack type
+ STMDB sp!, {r3, r4} // Save interrupt stack type and SPSR
+ STR sp, [r0, #8] // Save stack pointer in thread control
+ // block
+
+ /* Save the remaining time-slice and disable it. */
+ // if (_tx_timer_time_slice[core])
+ // {
+
+ LDR r3, =_tx_timer_interrupt_active // Pickup timer interrupt active flag's address
+_tx_wait_for_timer_to_finish
+ LDR r2, [r3, #0] // Pickup timer interrupt active flag
+ CMP r2, #0 // Is the timer interrupt active?
+ BNE _tx_wait_for_timer_to_finish // If timer interrupt is active, wait until it completes
+
+ LDR r3, =_tx_timer_time_slice // Pickup time-slice variable address
+ ADD r3, r3, r12 // Build index to core's time slice
+ LDR r2, [r3, #0] // Pickup time-slice
+ CMP r2, #0 // Is it active?
+ BEQ __tx_thread_dont_save_ts // No, don't save it
+
+ // _tx_thread_current_ptr[core] -> tx_thread_time_slice = _tx_timer_time_slice[core];
+ // _tx_timer_time_slice[core] = 0;
+
+ STR r2, [r0, #24] // Save thread's time-slice
+ MOV r2, #0 // Clear value
+ STR r2, [r3, #0] // Disable global time-slice flag
+
+ // }
+__tx_thread_dont_save_ts
+
+ /* Clear the current task pointer. */
+ // _tx_thread_current_ptr[core] = TX_NULL;
+
+ MOV r2, #0 // NULL value
+ STR r2, [r1, #0] // Clear current thread pointer
+
+ /* Set bit indicating this thread is ready for execution. */
+
+ LDR r2, [r0, #152] // Pickup the ready bit
+ ORR r2, r2, #0x8000 // Set ready bit (bit 15)
+ DMB // Ensure that accesses to shared resource have completed
+ STR r2, [r0, #152] // Make this thread ready for executing again
+
+ /* Return to the scheduler. */
+ // _tx_thread_schedule();
+
+ B _tx_thread_schedule // Return to scheduler
+ // }
+
+__tx_thread_idle_system_restore
+
+ /* Just return back to the scheduler! */
+
+ MOV r3, #SVC_MODE // Build SVC mode with interrupts disabled
+ MSR CPSR_c, r3 // Change to SVC mode
+ B _tx_thread_schedule // Return to scheduler
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s
new file mode 100644
index 00000000..96448b4a
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s
@@ -0,0 +1,191 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_state
+ IMPORT _tx_thread_current_ptr
+ IMPORT __tx_irq_processing_return
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ IMPORT _tx_execution_isr_enter
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_context_save SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_context_save(VOID)
+// {
+ EXPORT _tx_thread_context_save
+_tx_thread_context_save
+
+ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
+ out, we are in IRQ mode, and all registers are intact. */
+
+ /* Check for a nested interrupt condition. */
+ // if (_tx_thread_system_state[core]++)
+ // {
+
+ STMDB sp!, {r0-r3} // Save some working registers
+
+ /* Save the rest of the scratch registers on the stack and return to the
+ calling ISR. */
+
+ MRS r0, SPSR // Pickup saved SPSR
+ SUB lr, lr, #4 // Adjust point of interrupt
+ STMDB sp!, {r0, r10, r12, lr} // Store other registers
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable FIQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+
+ LDR r3, =_tx_thread_system_state // Pickup address of system state var
+ ADD r3, r3, r12 // Build index into the system state array
+ LDR r2, [r3, #0] // Pickup system state
+ CMP r2, #0 // Is this the first interrupt?
+ BEQ __tx_thread_not_nested_save // Yes, not a nested context save
+
+ /* Nested interrupt condition. */
+
+ ADD r2, r2, #1 // Increment the interrupt counter
+ STR r2, [r3, #0] // Store it back in the variable
+
+ /* Return to the ISR. */
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ B __tx_irq_processing_return // Continue IRQ processing
+
+__tx_thread_not_nested_save
+ // }
+
+ /* Otherwise, not nested, check to see if a thread was running. */
+ // else if (_tx_thread_current_ptr[core])
+ // {
+
+ ADD r2, r2, #1 // Increment the interrupt counter
+ STR r2, [r3, #0] // Store it back in the variable
+ LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ ADD r1, r1, r12 // Build index into current thread ptr
+ LDR r0, [r1, #0] // Pickup current thread pointer
+ CMP r0, #0 // Is it NULL?
+ BEQ __tx_thread_idle_system_save // If so, interrupt occurred in
+ // scheduling loop - nothing needs saving!
+
+ /* Save the current stack pointer in the thread's control block. */
+ // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp;
+
+ /* Switch to the system stack. */
+ // sp = _tx_thread_system_stack_ptr;
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ B __tx_irq_processing_return // Continue IRQ processing
+
+ // }
+ // else
+ // {
+
+__tx_thread_idle_system_save
+
+ /* Interrupt occurred in the scheduling loop. */
+
+ /* Not much to do here, just adjust the stack pointer, and return to IRQ
+ processing. */
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ ADD sp, sp, #32 // Recover saved registers
+ B __tx_irq_processing_return // Continue IRQ processing
+
+ // }
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_control.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_control.s
new file mode 100644
index 00000000..f76bb3a8
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_control.s
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+INT_MASK EQU 0xC0 // Interrupt bit mask
+ ELSE
+INT_MASK EQU 0x80 // Interrupt bit mask
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_control SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is responsible for changing the interrupt lockout */
+/* posture of the system. */
+/* */
+/* INPUT */
+/* */
+/* new_posture New interrupt lockout posture */
+/* */
+/* OUTPUT */
+/* */
+/* old_posture Old interrupt lockout posture */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* Application Code */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_control(UINT new_posture)
+// {
+ EXPORT _tx_thread_interrupt_control
+_tx_thread_interrupt_control
+
+ /* Pickup current interrupt lockout posture. */
+
+ MRS r3, CPSR // Pickup current CPSR
+ BIC r1, r3, #INT_MASK // Clear interrupt lockout bits
+ ORR r1, r1, r0 // Or-in new interrupt lockout bits
+
+ /* Apply the new interrupt posture. */
+
+ MSR CPSR_c, r1 // Setup new CPSR
+ AND r0, r3, #INT_MASK // Return previous interrupt mask
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_disable.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_disable.s
new file mode 100644
index 00000000..3197ab46
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_disable.s
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_disable SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// UINT _tx_thread_interrupt_disable(void)
+// {
+ EXPORT _tx_thread_interrupt_disable
+_tx_thread_interrupt_disable
+
+ /* Pickup current interrupt lockout posture. */
+
+ MRS r0, CPSR // Pickup current CPSR
+
+ /* Mask interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ
+ ELSE
+ CPSID i // Disable IRQ
+ ENDIF
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_restore.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_restore.s
new file mode 100644
index 00000000..e1419f01
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_interrupt_restore.s
@@ -0,0 +1,74 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_interrupt_restore SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_interrupt_restore
+_tx_thread_interrupt_restore
+
+ /* Apply the new interrupt posture. */
+
+ MSR CPSR_c, r0 // Setup new CPSR
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_end.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_end.s
new file mode 100644
index 00000000..953e8128
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_end.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 */
+/** */
+/** Thread */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+DISABLE_INTS EQU 0xC0 // Disable IRQ & FIQ interrupts
+ ELSE
+DISABLE_INTS EQU 0x80 // Disable IRQ interrupts
+ ENDIF
+MODE_MASK EQU 0x1F // Mode mask
+IRQ_MODE_BITS EQU 0x12 // IRQ mode bits
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_irq_nesting_end SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is called by the application from IRQ mode after */
+/* _tx_thread_irq_nesting_start has been called and switches the IRQ */
+/* processing from system mode back to IRQ mode prior to the ISR */
+/* calling _tx_thread_context_restore. Note that this function */
+/* assumes the system stack pointer is in the same position after */
+/* nesting start function was called. */
+/* */
+/* This function assumes that the system mode stack pointer was setup */
+/* during low-level initialization (tx_initialize_low_level.s). */
+/* */
+/* This function returns with IRQ interrupts disabled. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_irq_nesting_end(VOID)
+// {
+ EXPORT _tx_thread_irq_nesting_end
+_tx_thread_irq_nesting_end
+ MOV r3,lr // Save ISR return address
+ MRS r0, CPSR // Pickup the CPSR
+ ORR r0, r0, #DISABLE_INTS // Build disable interrupt value
+ MSR CPSR_c, r0 // Disable interrupts
+ LDMIA sp!, {lr, r1} // Pickup saved lr (and r1 throw-away for
+ // 8-byte alignment logic)
+ BIC r0, r0, #MODE_MASK // Clear mode bits
+ ORR r0, r0, #IRQ_MODE_BITS // Build IRQ mode CPSR
+ MSR CPSR_c, r0 // Re-enter IRQ mode
+ IF {INTER} = {TRUE}
+ BX r3 // Return to caller
+ ELSE
+ MOV pc, r3 // Return to caller
+ ENDIF
+// }
+ END
+
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_start.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_start.s
new file mode 100644
index 00000000..07607ac7
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_irq_nesting_start.s
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+IRQ_DISABLE EQU 0x80 // IRQ disable bit
+MODE_MASK EQU 0x1F // Mode mask
+SYS_MODE_BITS EQU 0x1F // System mode bits
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_irq_nesting_start SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is called by the application from IRQ mode after */
+/* _tx_thread_context_save has been called and switches the IRQ */
+/* processing to the system mode so nested IRQ interrupt processing */
+/* is possible (system mode has its own "lr" register). Note that */
+/* this function assumes that the system mode stack pointer was setup */
+/* during low-level initialization (tx_initialize_low_level.s). */
+/* */
+/* This function returns with IRQ interrupts enabled. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ISRs */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_irq_nesting_start(VOID)
+// {
+ EXPORT _tx_thread_irq_nesting_start
+_tx_thread_irq_nesting_start
+ MOV r3,lr // Save ISR return address
+ MRS r0, CPSR // Pickup the CPSR
+ BIC r0, r0, #MODE_MASK // Clear the mode bits
+ ORR r0, r0, #SYS_MODE_BITS // Build system mode CPSR
+ MSR CPSR_c, r0 // Enter system mode
+ STMDB sp!, {lr, r1} // Push the system mode lr on the system mode stack
+ // and push r1 just to keep 8-byte alignment
+ BIC r0, r0, #IRQ_DISABLE // Build enable IRQ CPSR
+ MSR CPSR_c, r0 // Enter system mode
+ IF {INTER} = {TRUE}
+ BX r3 // Return to caller
+ ELSE
+ MOV pc, r3 // Return to caller
+ ENDIF
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_schedule.s
new file mode 100644
index 00000000..ebb0ca5c
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_schedule.s
@@ -0,0 +1,249 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_execute_ptr
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_timer_time_slice
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ IMPORT _tx_execution_thread_enter
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_schedule SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function waits for a thread control block pointer to appear in */
+/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
+/* in the variable, the corresponding thread is resumed. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_kernel_enter ThreadX entry function */
+/* _tx_thread_system_return Return to system from thread */
+/* _tx_thread_context_restore Restore thread's context */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_schedule(VOID)
+// {
+ EXPORT _tx_thread_schedule
+_tx_thread_schedule
+
+ /* Enable interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSIE if // Enable IRQ and FIQ interrupts
+ ELSE
+ CPSIE i // Enable IRQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+
+ LDR r1, =_tx_thread_execute_ptr // Address of thread execute ptr
+ ADD r1, r1, r12 // Build offset to execute ptr for this core
+
+ /* Lockout interrupts transfer control to it. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ /* Wait for a thread to execute. */
+ // do
+ // {
+
+ LDR r0, [r1, #0] // Pickup next thread to execute
+ CMP r0, #0 // Is it NULL?
+ BEQ _tx_thread_schedule // If so, keep looking for a thread
+
+ // }
+ // while(_tx_thread_execute_ptr[core] == TX_NULL);
+
+ /* Now make sure the thread's ready bit is set. */
+
+ LDR r2, [r0, #152] // Pickup the thread ready bit
+ AND r3, r2, #0x8000 // Isolate the ready bit
+ CMP r3, #0 // Is it set?
+ BEQ _tx_thread_schedule // If not, restart the scheduling loop
+
+ /* Yes! We have a thread to execute. ;
+
+ /* Clear the ready bit. */
+
+ BIC r2, r2, #0x8000 // Clear ready bit
+ STR r2, [r0, #152] // Store it back in the thread control block
+ DMB
+
+ /* Setup the current thread pointer. */
+ // _tx_thread_current_ptr[core] = _tx_thread_execute_ptr[core];
+
+ LDR r1, =_tx_thread_current_ptr // Pickup address of current thread
+ ADD r1, r1, r12 // Build index into the current thread array
+ STR r0, [r1, #0] // Setup current thread pointer
+
+ /* Increment the run count for this thread. */
+ // _tx_thread_current_ptr[core] -> tx_thread_run_count++;
+
+ LDR r2, [r0, #4] // Pickup run counter
+ LDR r3, [r0, #24] // Pickup time-slice for this thread
+ ADD r2, r2, #1 // Increment thread run-counter
+ STR r2, [r0, #4] // Store the new run counter
+
+ /* Setup time-slice, if present. */
+ // _tx_timer_time_slice[core] = _tx_thread_current_ptr[core] -> tx_thread_time_slice;
+
+ LDR r2, =_tx_timer_time_slice // Pickup address of time slice
+ // variable
+ ADD r2, r2, r12 // Build index into the time-slice array
+ LDR sp, [r0, #8] // Switch stack pointers
+ STR r3, [r2, #0] // Setup time-slice
+
+ /* Switch to the thread's stack. */
+ // sp = _tx_thread_execute_ptr[core] -> tx_thread_stack_ptr;
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the thread entry function to indicate the thread is executing. */
+
+ MOV r5, r0 // Save r0
+ BL _tx_execution_thread_enter // Call the thread execution enter function
+ MOV r0, r5 // Restore r0
+ ENDIF
+
+ /* Determine if an interrupt frame or a synchronous task suspension frame
+ is present. */
+
+ LDMIA sp!, {r4, r5} // Pickup the stack type and saved CPSR
+ CMP r4, #0 // Check for synchronous context switch
+ BEQ _tx_solicited_return
+ MSR SPSR_cxsf, r5 // Setup SPSR for return
+ IF {TARGET_FPU_VFP} = {TRUE}
+ LDR r1, [r0, #160] // Pickup the VFP enabled flag
+ CMP r1, #0 // Is the VFP enabled?
+ BEQ _tx_skip_interrupt_vfp_restore // No, skip VFP interrupt restore
+ VLDMIA sp!, {D0-D15} // Recover D0-D15
+ LDR r4, [sp], #4 // Pickup FPSCR
+ VMSR FPSCR, r4 // Restore FPSCR
+_tx_skip_interrupt_vfp_restore
+ ENDIF
+ LDMIA sp!, {r0-r12, lr, pc}^ // Return to point of thread interrupt
+
+_tx_solicited_return
+ IF {TARGET_FPU_VFP} = {TRUE}
+ MSR CPSR_cxsf, r5 // Recover CPSR
+ LDR r1, [r0, #160] // Pickup the VFP enabled flag
+ CMP r1, #0 // Is the VFP enabled?
+ BEQ _tx_skip_solicited_vfp_restore // No, skip VFP solicited restore
+ VLDMIA sp!, {D0-D15} // Recover D0-D15
+ LDR r4, [sp], #4 // Pickup FPSCR
+ VMSR FPSCR, r4 // Restore FPSCR
+_tx_skip_solicited_vfp_restore
+ ENDIF
+ MSR CPSR_cxsf, r5 // Recover CPSR
+ LDMIA sp!, {r4-r11, lr} // Return to thread synchronously
+ BX lr // Return to caller
+
+// }
+
+
+ IF {TARGET_FPU_VFP} = {TRUE}
+ EXPORT tx_thread_vfp_enable
+tx_thread_vfp_enable
+ MRS r2, CPSR // Pickup the CPSR
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+ MRC p15, 0, r1, c0, c0, 5 // Read CPU ID register
+ AND r1, r1, #0x03 // Mask off, leaving the CPU ID field
+ LSL r1, r1, #2 // Build offset to array indexes
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ ADD r0, r0, r1 // Build index into the current thread array
+ LDR r1, [r0] // Pickup current thread pointer
+ CMP r1, #0 // Check for NULL thread pointer
+ BEQ __tx_no_thread_to_enable // If NULL, skip VFP enable
+ MOV r0, #1 // Build enable value
+ STR r0, [r1, #160] // Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
+__tx_no_thread_to_enable
+ MSR CPSR_cxsf, r2 // Recover CPSR
+ BX LR // Return to caller
+
+ EXPORT tx_thread_vfp_disable
+tx_thread_vfp_disable
+ MRS r2, CPSR // Pickup the CPSR
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+ MRC p15, 0, r1, c0, c0, 5 // Read CPU ID register
+ AND r1, r1, #0x03 // Mask off, leaving the CPU ID field
+ LSL r1, r1, #2 // Build offset to array indexes
+ LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
+ ADD r0, r0, r1 // Build index into the current thread array
+ LDR r1, [r0] // Pickup current thread pointer
+ CMP r1, #0 // Check for NULL thread pointer
+ BEQ __tx_no_thread_to_disable // If NULL, skip VFP disable
+ MOV r0, #0 // Build disable value
+ STR r0, [r1, #160] // Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
+__tx_no_thread_to_disable
+ MSR CPSR_cxsf, r2 // Recover CPSR
+ BX LR // Return to caller
+ ENDIF
+
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_get.s
new file mode 100644
index 00000000..bd917792
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_get.s
@@ -0,0 +1,72 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_core_get SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets the currently running core number and returns it.*/
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* Core ID */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Source */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_core_get
+_tx_thread_smp_core_get
+ MRC p15, 0, r0, c0, c0, 5 // Read CPU ID register
+ AND r0, r0, #0x03 // Mask off, leaving the CPU ID field
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_preempt.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_preempt.s
new file mode 100644
index 00000000..20a6ab29
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_core_preempt.s
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT send_sgi
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_core_preempt SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function preempts the specified core in situations where the */
+/* thread corresponding to this core is no longer ready or when the */
+/* core must be used for a higher-priority thread. If the specified is */
+/* the current core, this processing is skipped since the will give up */
+/* control subsequently on its own. */
+/* */
+/* INPUT */
+/* */
+/* core The core to preempt */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Source */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_core_preempt
+_tx_thread_smp_core_preempt
+
+ STMDB sp!, {lr, r4} // Save the lr and r4 register on the stack
+
+ /* Place call to send inter-processor interrupt here! */
+
+ DSB //
+ MOV r1, #1 // Build parameter list
+ LSL r1, r1, r0 //
+ MOV r0, #0 //
+ MOV r2, #0 //
+ BL send_sgi // Make call to send inter-processor interrupt
+
+ LDMIA sp!, {lr, r4} // Recover lr register and r4
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_state_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_state_get.s
new file mode 100644
index 00000000..32bcb44e
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_state_get.s
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_state
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_current_state_get SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is gets the current state of the calling core. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_current_state_get
+_tx_thread_smp_current_state_get
+
+ MRS r3, CPSR // Pickup current CPSR
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r2, c0, c0, 5 // Read CPU ID register
+ AND r2, r2, #0x03 // Mask off, leaving the CPU ID field
+ LSL r2, r2, #2 // Build offset to array indexes
+
+ LDR r1, =_tx_thread_system_state // Pickup start of the current state array
+ ADD r1, r1, r2 // Build index into the current state array
+ LDR r0, [r1] // Pickup state for this core
+ MSR CPSR_c, r3 // Restore CPSR
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_thread_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_thread_get.s
new file mode 100644
index 00000000..0e50c725
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_current_thread_get.s
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+ IMPORT _tx_thread_current_ptr
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_current_thread_get SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is gets the current thread of the calling core. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_current_thread_get
+_tx_thread_smp_current_thread_get
+
+ MRS r3, CPSR // Pickup current CPSR
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r2, c0, c0, 5 // Read CPU ID register
+ AND r2, r2, #0x03 // Mask off, leaving the CPU ID field
+ LSL r2, r2, #2 // Build offset to array indexes
+
+ LDR r1, =_tx_thread_current_ptr // Pickup start of the current thread array
+ ADD r1, r1, r2 // Build index into the current thread array
+ LDR r0, [r1] // Pickup current thread for this core
+ MSR CPSR_c, r3 // Restore CPSR
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_initialize_wait.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_initialize_wait.s
new file mode 100644
index 00000000..e7befb3d
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_initialize_wait.s
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_state
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_smp_release_cores_flag
+ IMPORT _tx_thread_schedule
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_initialize_wait SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is the place where additional cores wait until */
+/* initialization is complete before they enter the thread scheduling */
+/* loop. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_schedule Thread scheduling loop */
+/* */
+/* CALLED BY */
+/* */
+/* Hardware */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_initialize_wait
+_tx_thread_smp_initialize_wait
+
+ /* Lockout interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r10, r10, #2 // Build offset to array indexes
+
+ /* Make sure the system state for this core is TX_INITIALIZE_IN_PROGRESS before we check the release
+ flag. */
+
+ LDR r3, =_tx_thread_system_state // Build address of system state variable
+ ADD r3, r3, r10 // Build index into the system state array
+ LDR r2, =0xF0F0F0F0 // Build TX_INITIALIZE_IN_PROGRESS flag
+wait_for_initialize
+ LDR r1, [r3] // Pickup system state
+ CMP r1, r2 // Has initialization completed?
+ BNE wait_for_initialize // If different, wait here!
+
+ /* Pickup the release cores flag. */
+
+ LDR r2, =_tx_thread_smp_release_cores_flag // Build address of release cores flag
+
+wait_for_release
+ LDR r3, [r2] // Pickup the flag
+ CMP r3, #0 // Is it set?
+ BEQ wait_for_release // Wait for the flag to be set
+
+ /* Core 0 has released this core. */
+
+ /* Clear this core's system state variable. */
+
+ LDR r3, =_tx_thread_system_state // Build address of system state variable
+ ADD r3, r3, r10 // Build index into the system state array
+ MOV r0, #0 // Build clear value
+ STR r0, [r3] // Clear this core's entry in the system state array
+
+ /* Now wait for core 0 to finish it's initialization. */
+
+ LDR r3, =_tx_thread_system_state // Build address of system state variable of logical 0
+
+core_0_wait_loop
+ LDR r2, [r3] // Pickup system state for core 0
+ CMP r2, #0 // Is it 0?
+ BNE core_0_wait_loop // No, keep waiting for core 0 to finish its initialization
+
+ /* Initialize is complete, enter the scheduling loop! */
+
+ B _tx_thread_schedule // Enter scheduling loop for this core!
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_low_level_initialize.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_low_level_initialize.s
new file mode 100644
index 00000000..b5edd74b
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_low_level_initialize.s
@@ -0,0 +1,72 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_low_level_initialize SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function performs low-level initialization of the booting */
+/* core. */
+/* */
+/* INPUT */
+/* */
+/* number_of_cores Number of cores */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_initialize_high_level ThreadX high-level init */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_low_level_initialize
+_tx_thread_smp_low_level_initialize
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_protect.s
new file mode 100644
index 00000000..11b81128
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_protect.s
@@ -0,0 +1,127 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_smp_protection
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_protect SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets protection for running inside the ThreadX */
+/* source. This is acomplished by a combination of a test-and-set */
+/* flag and periodically disabling interrupts. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* Previous Status Register */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Source */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_protect
+_tx_thread_smp_protect
+
+ MRS r3, CPSR // Pickup current CPSR
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r2, c0, c0, 5 // Read CPU ID register
+ AND r2, r2, #0x03 // Mask off, leaving the CPU ID field
+ LDR r0,=_tx_thread_smp_protection // Build address to protection structure
+ LDR r1, [r0, #8] // Pickup the owning core
+ CMP r1, r2 // Is it this core?
+ BEQ _owned // Yes, the protection is already owned
+
+ LDREX r1, [r0] // Pickup the protection
+ CMP r1, #0 // Is it available?
+ BEQ _get_protection // Yes, get the protection
+ MSR CPSR_c, r3 // Restore CPSR
+ WFE // Go into standby
+ B _tx_thread_smp_protect // On waking restart the protection attempt
+
+_get_protection
+ MOV r1, #1 // Build lock value
+ STREX r2, r1, [r0] // Attempt to get protection
+ CMP r2, #0x0 // Check whether store completed successfully (0=succeeded)
+ MSRNE CPSR_c, r3 // If unsuccessful, restore CPSR
+ BNE _tx_thread_smp_protect // If unsuccessful, try the process again!
+ DMB ;
+ MRC p15, 0, r2, c0, c0, 5 // Read CPU ID register
+ AND r2, r2, #0x03 // Mask off, leaving the CPU ID field
+ STR r2, [r0, #8] // Save owning core
+
+ IF :DEF:TX_MPCORE_DEBUG_ENABLE
+ LSL r2, r2, #2 // Build offset to array indexes
+ LDR r1, =_tx_thread_current_ptr // Pickup start of the current thread array
+ ADD r1, r1, r2 // Build index into the current thread array
+ LDR r2, [r1] // Pickup current thread for this core
+ STR r2, [r0, #4] // Save current thread pointer
+ STR LR, [r0, #16] // Save caller's return address
+ STR r3, [r0, #20] // Save CPSR
+ ENDIF
+_owned
+ LDR r1, [r0, #12] // Pickup ownership count
+ ADD r1, r1, #1 // Increment ownership count
+ STR r1, [r0, #12] // Store new ownership count
+
+ MOV r0, r3 // Return the CPSR
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s
new file mode 100644
index 00000000..fdaab14b
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s
@@ -0,0 +1,75 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_time_get SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function gets the global time value that is used for debug */
+/* information and event tracing. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* 32-bit time stamp */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Source */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_time_get
+_tx_thread_smp_time_get
+
+ MRC p15, 4, r0, c15, c0, 0 // Read periph base address
+ LDR r0, [r0, #0x604] // Read count register
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_unprotect.s
new file mode 100644
index 00000000..b431e485
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_unprotect.s
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_thread_smp_protection
+ IMPORT _tx_thread_preempt_disable
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_smp_unprotect SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function releases previously obtained protection. The supplied */
+/* previous SR is restored. If the value of _tx_thread_system_state */
+/* and _tx_thread_preempt_disable are both zero, then multithreading */
+/* is enabled as well. */
+/* */
+/* INPUT */
+/* */
+/* Previous Status Register */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX Source */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+ EXPORT _tx_thread_smp_unprotect
+_tx_thread_smp_unprotect
+
+ /* Lockout interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ LDR r1,=_tx_thread_smp_protection // Build address of protection structure
+ MRC p15, 0, r3, c0, c0, 5 // Read CPU ID register
+ AND r3, r3, #0x03 // Mask off, leaving the CPU ID field
+ LDR r2, [r1, #8] // Pickup the owning core
+ CMP r2, r3 // Is it this core?
+ BNE _still_protected // If this is not the owning core, protection is in force elsewhere
+
+ LDR r2, [r1, #12] // Pickup the protection count
+ CMP r2, #0 // Check to see if the protection is still active
+ BEQ _still_protected // If the protection count is zero, protection has already been cleared
+
+ SUB r2, r2, #1 // Decrement the protection count
+ STR r2, [r1, #12] // Store the new count back
+ CMP r2, #0 // Check to see if the protection is still active
+ BNE _still_protected // If the protection count is non-zero, protection is still in force
+ LDR r2,=_tx_thread_preempt_disable // Build address of preempt disable flag
+ LDR r3, [r2] // Pickup preempt disable flag
+ CMP r3, #0 // Is the preempt disable flag set?
+ BNE _still_protected // Yes, skip the protection release
+ MOV r2, #0xFFFFFFFF // Build invalid value
+ STR r2, [r1, #8] // Mark the protected core as invalid
+ IF :DEF:TX_MPCORE_DEBUG_ENABLE
+ STR LR, [r0, #16] // Save caller's return address
+ ENDIF
+ DMB // Ensure that accesses to shared resource have completed
+ MOV r2, #0 // Build release protection value
+ STR r2, [r1] // Release the protection
+ DSB // To ensure update of the protection occurs before other CPUs awake
+ SEV // Send event to other CPUs, wakes anyone waiting on the protection (using WFE)
+
+_still_protected
+ MSR CPSR_c, r0 // Restore CPSR
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_stack_build.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_stack_build.s
new file mode 100644
index 00000000..425bc4e9
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_stack_build.s
@@ -0,0 +1,159 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+SVC_MODE EQU 0x13 // SVC mode
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+CPSR_MASK EQU 0xDF // Mask initial CPSR, IRQ & FIQ ints enabled
+ ELSE
+CPSR_MASK EQU 0x9F // Mask initial CPSR, IRQ ints enabled
+ ENDIF
+
+THUMB_BIT EQU 0x20 // Thumb-bit
+
+ AREA ||.text||, CODE, READONLY
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_stack_build SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function builds a stack frame on the supplied thread's stack. */
+/* The stack frame results in a fake interrupt return to the supplied */
+/* function pointer. */
+/* */
+/* INPUT */
+/* */
+/* thread_ptr Pointer to thread control blk */
+/* function_ptr Pointer to return function */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _tx_thread_create Create thread service */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
+// {
+ EXPORT _tx_thread_stack_build
+_tx_thread_stack_build
+
+
+ /* Build a fake interrupt frame. The form of the fake interrupt stack
+ on the Cortex-R8 should look like the following after it is built:
+
+ Stack Top: 1 Interrupt stack frame type
+ CPSR Initial value for CPSR
+ a1 (r0) Initial value for a1
+ a2 (r1) Initial value for a2
+ a3 (r2) Initial value for a3
+ a4 (r3) Initial value for a4
+ v1 (r4) Initial value for v1
+ v2 (r5) Initial value for v2
+ v3 (r6) Initial value for v3
+ v4 (r7) Initial value for v4
+ v5 (r8) Initial value for v5
+ sb (r9) Initial value for sb
+ sl (r10) Initial value for sl
+ fp (r11) Initial value for fp
+ ip (r12) Initial value for ip
+ lr (r14) Initial value for lr
+ pc (r15) Initial value for pc
+ 0 For stack backtracing
+
+ Stack Bottom: (higher memory address) */
+
+ LDR r2, [r0, #16] // Pickup end of stack area
+ BIC r2, r2, #7 // Ensure 8-byte alignment
+ SUB r2, r2, #76 // Allocate space for the stack frame
+
+ /* Actually build the stack frame. */
+
+ MOV r3, #1 // Build interrupt stack type
+ STR r3, [r2, #0] // Store stack type
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #8] // Store initial r0
+ STR r3, [r2, #12] // Store initial r1
+ STR r3, [r2, #16] // Store initial r2
+ STR r3, [r2, #20] // Store initial r3
+ STR r3, [r2, #24] // Store initial r4
+ STR r3, [r2, #28] // Store initial r5
+ STR r3, [r2, #32] // Store initial r6
+ STR r3, [r2, #36] // Store initial r7
+ STR r3, [r2, #40] // Store initial r8
+ STR r3, [r2, #44] // Store initial r9
+ LDR r3, [r0, #12] // Pickup stack starting address
+ STR r3, [r2, #48] // Store initial r10 (sl)
+ MOV r3, #0 // Build initial register value
+ STR r3, [r2, #52] // Store initial r11
+ STR r3, [r2, #56] // Store initial r12
+ STR r3, [r2, #60] // Store initial lr
+ STR r1, [r2, #64] // Store initial pc
+ STR r3, [r2, #68] // 0 for back-trace
+
+ MRS r3, CPSR // Pickup CPSR
+ BIC r3, r3, #CPSR_MASK // Mask mode bits of CPSR
+ ORR r3, r3, #SVC_MODE // Build CPSR, SVC mode, interrupts enabled
+ BIC r3, r3, #THUMB_BIT // Clear Thumb-bit by default
+ AND r1, r1, #1 // Determine if the entry function is in Thumb mode
+ CMP r1, #1 // Is the Thumb-bit set?
+ ORREQ r3, r3, #THUMB_BIT // Yes, set the Thumb-bit
+ STR r3, [r2, #4] // Store initial CPSR
+
+ /* Setup stack pointer. */
+ // thread_ptr -> tx_thread_stack_ptr = r2;
+
+ STR r2, [r0, #8] // Save stack pointer in thread's
+ // control block
+
+
+ /* Set ready bit in thread control block. */
+
+ LDR r2, [r0, #152] // Pickup word with ready bit
+ ORR r2, r2, #0x8000 // Build ready bit set
+ STR r2, [r0, #152] // Set ready bit
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+// }
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s
new file mode 100644
index 00000000..1803e190
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s
@@ -0,0 +1,193 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_current_ptr
+ IMPORT _tx_timer_time_slice
+ IMPORT _tx_thread_schedule
+ IMPORT _tx_thread_preempt_disable
+ IMPORT _tx_thread_smp_protection
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ IMPORT _tx_execution_thread_exit
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_system_return SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function is target processor specific. It is used to transfer */
+/* control from a thread back to the ThreadX system. Only a */
+/* minimal context is saved since the compiler assumes temp registers */
+/* are going to get slicked by a function call anyway. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_schedule Thread scheduling loop */
+/* */
+/* CALLED BY */
+/* */
+/* ThreadX components */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_system_return(VOID)
+// {
+ EXPORT _tx_thread_system_return
+_tx_thread_system_return
+
+ /* Save minimal context on the stack. */
+
+ STMDB sp!, {r4-r11, lr} // Save minimal context
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+
+ LDR r3, =_tx_thread_current_ptr // Pickup address of current ptr
+ ADD r3, r3, r12 // Build index into current ptr array
+ LDR r0, [r3, #0] // Pickup current thread pointer
+ IF {TARGET_FPU_VFP} = {TRUE}
+ LDR r1, [r0, #160] // Pickup the VFP enabled flag
+ CMP r1, #0 // Is the VFP enabled?
+ BEQ _tx_skip_solicited_vfp_save // No, skip VFP solicited save
+ VMRS r4, FPSCR // Pickup the FPSCR
+ STR r4, [sp, #-4]! // Save FPSCR
+ VSTMDB sp!, {D0-D15} // Save D0-D15
+_tx_skip_solicited_vfp_save
+ ENDIF
+ MOV r4, #0 // Build a solicited stack type
+ MRS r5, CPSR // Pickup the CPSR
+ STMDB sp!, {r4-r5} // Save type and CPSR
+
+ /* Lockout interrupts. */
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ELSE
+ CPSID i // Disable IRQ interrupts
+ ENDIF
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the thread exit function to indicate the thread is no longer executing. */
+
+ MOV r4, r0 // Save r0
+ MOV r5, r3 // Save r3
+ MOV r6, r12 // Save r12
+ BL _tx_execution_thread_exit // Call the thread exit function
+ MOV r3, r5 // Recover r3
+ MOV r0, r4 // Recover r4
+ MOV r12,r6 // Recover r12
+ ENDIF
+
+ LDR r2, =_tx_timer_time_slice // Pickup address of time slice
+ ADD r2, r2, r12 // Build index into time-slice array
+ LDR r1, [r2, #0] // Pickup current time slice
+
+ /* Save current stack and switch to system stack. */
+ // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp;
+ // sp = _tx_thread_system_stack_ptr[core];
+
+ STR sp, [r0, #8] // Save thread stack pointer
+
+ /* Determine if the time-slice is active. */
+ // if (_tx_timer_time_slice[core])
+ // {
+
+ MOV r4, #0 // Build clear value
+ CMP r1, #0 // Is a time-slice active?
+ BEQ __tx_thread_dont_save_ts // No, don't save the time-slice
+
+ /* Save time-slice for the thread and clear the current time-slice. */
+ // _tx_thread_current_ptr[core] -> tx_thread_time_slice = _tx_timer_time_slice[core];
+ // _tx_timer_time_slice[core] = 0;
+
+ STR r4, [r2, #0] // Clear time-slice
+ STR r1, [r0, #24] // Save current time-slice
+
+ // }
+__tx_thread_dont_save_ts
+
+ /* Clear the current thread pointer. */
+ // _tx_thread_current_ptr[core] = TX_NULL;
+
+ STR r4, [r3, #0] // Clear current thread pointer
+
+ /* Set ready bit in thread control block. */
+
+ LDR r2, [r0, #152] // Pickup word with ready bit
+ ORR r2, r2, #0x8000 // Build ready bit set
+ DMB // Ensure that accesses to shared resource have completed
+ STR r2, [r0, #152] // Set ready bit
+
+ /* Now clear protection. It is assumed that protection is in force whenever this routine is called. */
+
+ LDR r3, =_tx_thread_smp_protection // Pickup address of protection structure
+
+ IF :DEF:TX_MPCORE_DEBUG_ENABLE
+ STR lr, [r3, #24] // Save last caller
+ LDR r2, [r3, #4] // Pickup owning thread
+ CMP r0, r2 // Is it the same as the current thread?
+__error_loop
+ BNE __error_loop // If not, we have a problem!!
+ ENDIF
+
+ LDR r1, =_tx_thread_preempt_disable // Build address to preempt disable flag
+ MOV r2, #0 // Build clear value
+ STR r2, [r1, #0] // Clear preempt disable flag
+ STR r2, [r3, #12] // Clear protection count
+ MOV r1, #0xFFFFFFFF // Build invalid value
+ STR r1, [r3, #8] // Set core to an invalid value
+ DMB // Ensure that accesses to shared resource have completed
+ STR r2, [r3] // Clear protection
+ DSB // To ensure update of the shared resource occurs before other CPUs awake
+ SEV // Send event to other CPUs, wakes anyone waiting on a mutex (using WFE)
+
+ B _tx_thread_schedule // Jump to scheduler!
+
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s
new file mode 100644
index 00000000..1aa88bcb
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s
@@ -0,0 +1,197 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_thread_system_state
+ IMPORT _tx_thread_current_ptr
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+ IMPORT _tx_execution_isr_enter
+ ENDIF
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_thread_vectored_context_save SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, 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 */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_thread_vectored_context_save(VOID)
+// {
+ EXPORT _tx_thread_vectored_context_save
+_tx_thread_vectored_context_save
+
+ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
+ out, we are in IRQ mode, and all registers are intact. */
+
+ /* Check for a nested interrupt condition. */
+ // if (_tx_thread_system_state[core]++)
+ // {
+
+ IF :DEF:TX_ENABLE_FIQ_SUPPORT
+ CPSID if // Disable IRQ and FIQ interrupts
+ ENDIF
+
+ /* Pickup the CPU ID. */
+
+ MRC p15, 0, r10, c0, c0, 5 // Read CPU ID register
+ AND r10, r10, #0x03 // Mask off, leaving the CPU ID field
+ LSL r12, r10, #2 // Build offset to array indexes
+
+ LDR r3, =_tx_thread_system_state // Pickup address of system state var
+ ADD r3, r3, r12 // Build index into the system state array
+ LDR r2, [r3, #0] // Pickup system state
+ CMP r2, #0 // Is this the first interrupt?
+ BEQ __tx_thread_not_nested_save // Yes, not a nested context save
+
+ /* Nested interrupt condition. */
+
+ ADD r2, r2, #1 // Increment the interrupt counter
+ STR r2, [r3, #0] // Store it back in the variable
+
+ /* Note: Minimal context of interrupted thread is already saved. */
+
+ /* Return to the ISR. */
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+__tx_thread_not_nested_save
+ // }
+
+ /* Otherwise, not nested, check to see if a thread was running. */
+ // else if (_tx_thread_current_ptr[core])
+ // {
+
+ ADD r2, r2, #1 // Increment the interrupt counter
+ STR r2, [r3, #0] // Store it back in the variable
+ LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
+ ADD r1, r1, r12 // Build index into current thread ptr
+ LDR r0, [r1, #0] // Pickup current thread pointer
+ CMP r0, #0 // Is it NULL?
+ BEQ __tx_thread_idle_system_save // If so, interrupt occurred in
+ // scheduling loop - nothing needs saving!
+
+ /* Note: Minimal context of interrupted thread is already saved. */
+
+ /* Save the current stack pointer in the thread's control block. */
+ // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp;
+
+ /* Switch to the system stack. */
+ // sp = _tx_thread_system_stack_ptr[core];
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ // }
+ // else
+ // {
+
+__tx_thread_idle_system_save
+
+ /* Interrupt occurred in the scheduling loop. */
+
+ /* Not much to do here, just adjust the stack pointer, and return to IRQ
+ processing. */
+
+ MOV r10, #0 // Clear stack limit
+
+ IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+
+ /* Call the ISR enter function to indicate an ISR is executing. */
+
+ PUSH {r12, lr} // Save ISR lr & r12
+ BL _tx_execution_isr_enter // Call the ISR enter function
+ POP {r12, lr} // Recover ISR lr & r12
+ ENDIF
+
+ ADD sp, sp, #32 // Recover saved registers
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+ // }
+// }
+
+ END
diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_timer_interrupt.s b/ports_smp/cortex_r8_smp/ac5/src/tx_timer_interrupt.s
new file mode 100644
index 00000000..87548265
--- /dev/null
+++ b/ports_smp/cortex_r8_smp/ac5/src/tx_timer_interrupt.s
@@ -0,0 +1,214 @@
+/**************************************************************************/
+/* */
+/* 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 */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+ IMPORT _tx_timer_time_slice
+ IMPORT _tx_timer_system_clock
+ IMPORT _tx_timer_current_ptr
+ IMPORT _tx_timer_list_start
+ IMPORT _tx_timer_list_end
+ IMPORT _tx_timer_expired_time_slice
+ IMPORT _tx_timer_expired
+ IMPORT _tx_thread_time_slice
+ IMPORT _tx_timer_expiration_process
+ IMPORT _tx_timer_interrupt_active
+ IMPORT _tx_thread_smp_protect
+ IMPORT _tx_thread_smp_unprotect
+ IMPORT _tx_trace_isr_enter_insert
+ IMPORT _tx_trace_isr_exit_insert
+
+ AREA ||.text||, CODE, READONLY
+ PRESERVE8
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _tx_timer_interrupt SMP/Cortex-R8/ARM */
+/* 6.2.0 */
+/* AUTHOR */
+/* */
+/* Scott Larson, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function processes the hardware timer interrupt. This */
+/* processing includes incrementing the system clock and checking for */
+/* time slice and/or timer expiration. If either is found, the */
+/* interrupt context save/restore functions are called along with the */
+/* expiration functions. */
+/* */
+/* INPUT */
+/* */
+/* None */
+/* */
+/* OUTPUT */
+/* */
+/* None */
+/* */
+/* CALLS */
+/* */
+/* _tx_thread_time_slice Time slice interrupted thread */
+/* _tx_thread_smp_protect Get SMP protection */
+/* _tx_thread_smp_unprotect Releast SMP protection */
+/* _tx_timer_expiration_process Timer expiration processing */
+/* */
+/* CALLED BY */
+/* */
+/* interrupt vector */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-31-2022 Scott Larson Initial Version 6.2.0 */
+/* */
+/**************************************************************************/
+// VOID _tx_timer_interrupt(VOID)
+// {
+ EXPORT _tx_timer_interrupt
+_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. */
+
+ MRC p15, 0, r0, c0, c0, 5 // Read CPU ID register
+ AND r0, r0, #0x03 // Mask off, leaving the CPU ID field
+ CMP r0, #0 // Only process timer interrupts from core 0 (to change this simply change the constant!)
+ BEQ __tx_process_timer // If the same process the interrupt
+ BX lr // Return to caller if not matched
+__tx_process_timer
+
+ STMDB sp!, {lr, r4} // Save the lr and r4 register on the stack
+ BL _tx_thread_smp_protect // Get protection
+ MOV r4, r0 // Save the return value in preserved register
+
+ LDR r1, =_tx_timer_interrupt_active // Pickup address of timer interrupt active count
+ LDR r0, [r1, #0] // Pickup interrupt active count
+ ADD r0, r0, #1 // Increment interrupt active count
+ STR r0, [r1, #0] // Store new interrupt active count
+ DMB // Ensure that accesses to shared resource have completed
+
+ /* Increment the system clock. */
+ // _tx_timer_system_clock++;
+
+ LDR r1, =_tx_timer_system_clock // Pickup address of system clock
+ LDR r0, [r1, #0] // Pickup system clock
+ ADD r0, r0, #1 // Increment system clock
+ STR r0, [r1, #0] // Store new system clock
+
+ /* Test for timer expiration. */
+ // if (*_tx_timer_current_ptr)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CMP r0, #0 // Check for previous timer expiration still active
+ BNE __tx_timer_done // If so, skip timer processing
+ LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer addr
+ LDR r0, [r1, #0] // Pickup current timer
+ LDR r2, [r0, #0] // Pickup timer list entry
+ CMP r2, #0 // Is there anything in the list?
+ BEQ __tx_timer_no_timer // No, just increment the timer
+
+ /* Set expiration flag. */
+ // _tx_timer_expired = TX_TRUE;
+
+ LDR r3, =_tx_timer_expired // Pickup expiration flag address
+ MOV r2, #1 // Build expired value
+ STR r2, [r3, #0] // Set expired flag
+ B __tx_timer_done // Finished timer processing
+
+ // }
+ // else
+ // {
+__tx_timer_no_timer
+
+ /* No timer expired, increment the timer pointer. */
+ // _tx_timer_current_ptr++;
+
+ ADD r0, r0, #4 // Move to next timer
+
+ /* Check for wrap-around. */
+ // if (_tx_timer_current_ptr == _tx_timer_list_end)
+
+ LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
+ LDR r2, [r3, #0] // Pickup list end
+ CMP r0, r2 // Are we at list end?
+ BNE __tx_timer_skip_wrap // No, skip wrap-around logic
+
+ /* Wrap to beginning of list. */
+ // _tx_timer_current_ptr = _tx_timer_list_start;
+
+ LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
+ LDR r0, [r3, #0] // Set current pointer to list start
+
+__tx_timer_skip_wrap
+
+ STR r0, [r1, #0] // Store new current timer pointer
+ // }
+
+__tx_timer_done
+
+ /* Did a timer expire? */
+ // if (_tx_timer_expired)
+ // {
+
+ LDR r1, =_tx_timer_expired // Pickup addr of expired flag
+ LDR r0, [r1, #0] // Pickup timer expired flag
+ CMP r0, #0 // Check for timer expiration
+ BEQ __tx_timer_dont_activate // If not set, skip timer activation
+
+ /* Process timer expiration. */
+ // _tx_timer_expiration_process();
+
+ BL _tx_timer_expiration_process // Call the timer expiration handling routine
+
+ // }
+__tx_timer_dont_activate
+
+ /* Call time-slice processing. */
+ // _tx_thread_time_slice();
+
+ BL _tx_thread_time_slice // Call time-slice processing
+
+ // }
+
+ LDR r1, =_tx_timer_interrupt_active // Pickup address of timer interrupt active count
+ LDR r0, [r1, #0] // Pickup interrupt active count
+ SUB r0, r0, #1 // Decrement interrupt active count
+ STR r0, [r1, #0] // Store new interrupt active count
+ DMB // Ensure that accesses to shared resource have completed
+
+ /* Release protection. */
+
+ MOV r0, r4 // Pass the previous status register back
+ BL _tx_thread_smp_unprotect // Release protection
+
+ LDMIA sp!, {lr, r4} // Recover lr register and r4
+ IF {INTER} = {TRUE}
+ BX lr // Return to caller
+ ELSE
+ MOV pc, lr // Return to caller
+ ENDIF
+
+// }
+ END