Release 6.2.0

This commit is contained in:
Tiejun Zhou
2022-10-26 23:41:13 +00:00
parent b871c33620
commit 3e8e85cdc1
173 changed files with 26264 additions and 3989 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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

View File

@@ -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
{
}
}

View File

@@ -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()
}

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
; ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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