diff options
| author | tameraw <[email protected]> | 2020-07-16 14:32:40 -0700 |
|---|---|---|
| committer | tameraw <[email protected]> | 2020-07-16 14:32:40 -0700 |
| commit | 2c35570dc9ced8690ea269d1efab201c361fea98 (patch) | |
| tree | a950c056346ab9a2260ba92a6be8ee3dd91ab7b6 /ports/cortex_a5x | |
| parent | f8e91d47625881614fe28efbcd43470922590d42 (diff) | |
updated to 6.0.1 and added additional processors/toolchains
Diffstat (limited to 'ports/cortex_a5x')
29 files changed, 4986 insertions, 0 deletions
diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/.cproject b/ports/cortex_a5x/ac6/example_build/sample_threadx/.cproject new file mode 100644 index 00000000..5ed0406b --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/.cproject @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> + <storageModule moduleId="org.eclipse.cdt.core.settings"> + <cconfiguration id="com.arm.eclipse.build.config.v6.exe.debug.1756493040"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.1756493040" 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.v6.exe.debug.1756493040" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug"> + <folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.1756493040." name="/" resourcePath=""> + <toolChain id="com.arm.toolchain.v6.exe.debug.299888552" name="ARM Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.debug"> + <targetPlatform id="com.arm.eclipse.build.config.v6.exe.debug.1756493040..302246591" name=""/> + <builder buildPath="${workspace_loc:/sample_threadx}/Debug" id="com.arm.toolchain.v6.builder.869166565" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.arm.toolchain.v6.builder"/> + <tool id="com.arm.tool.c.compiler.v6.1180490247" name="ARM C Compiler 6" superClass="com.arm.tool.c.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.min" id="com.arm.tool.c.compiler.v6.base.option.optlevel.526511916" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.tool.c.compiler.v6.base.options.debug.level.1965365158" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" valueType="enumerated"/> + <option id="com.arm.tool.c.compiler.v6.base.option.target.98510709" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="aarch64-arm-none-eabi" valueType="string"/> + <option id="com.arm.tool.c.compiler.v6.base.option.cpu.1703325529" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-a53+fp" valueType="string"/> + <option id="com.arm.tool.c.compiler.v6.base.option.defmac.1485103375" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols"> + <listOptionValue builtIn="false" value="STANDALONE"/> + </option> + <option id="com.arm.tool.c.compiler.v6.base.option.incpath.115625343" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath"> + <listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic}""/> + <listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_port}""/> + </option> + <inputType id="com.arm.tool.c.compiler.v6.base.input.1332371998" superClass="com.arm.tool.c.compiler.v6.base.input"/> + <inputType id="com.arm.tool.cpp.compiler.v6.base.input.122592929" superClass="com.arm.tool.cpp.compiler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.cpp.compiler.v6.757724458" name="ARM C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.min" id="com.arm.tool.c.compiler.v6.base.option.optlevel.328021275" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.tool.c.compiler.v6.base.options.debug.level.681507277" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/> + </tool> + <tool id="com.arm.tool.assembler.v6.1147311776" name="ARM Assembler 6" superClass="com.arm.tool.assembler.v6"> + <option defaultValue="com.arm.tool.assembler.v6.base.options.debug.level.std" id="com.arm.tool.assembler.v6.base.options.debug.level.895750985" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/> + <option id="com.arm.tool.assembler.v6.base.option.target.938598089" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" value="aarch64-arm-none-eabi" valueType="string"/> + <option id="com.arm.tool.assembler.v6.base.option.cpu.310599436" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" value="cortex-a53+fp" valueType="string"/> + <inputType id="com.arm.tool.assembler.v6.base.input.603158778" superClass="com.arm.tool.assembler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.c.linker.v6.996475472" name="ARM Linker 6" superClass="com.arm.tool.c.linker.v6"> + <option id="com.arm.tool.c.linker.option.entry.1400170036" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" value="start64" valueType="string"/> + <option id="com.arm.tool.c.linker.option.scatter.1388056657" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" value="..\sample_threadx.txt" valueType="string"/> + <option id="com.arm.tool.c.linker.option.imagemap.2104726082" name="Generate image map (--map)" superClass="com.arm.tool.c.linker.option.imagemap" value="true" valueType="boolean"/> + <option id="com.arm.tool.c.linker.option.verbose.2075899330" name="Verbose output (--verbose)" superClass="com.arm.tool.c.linker.option.verbose" value="true" valueType="boolean"/> + <option id="com.arm.tool.c.linker.option.totals.1648962874" name="List total code and data sizes of output image (--info=totals)" superClass="com.arm.tool.c.linker.option.totals" value="true" valueType="boolean"/> + <option id="com.arm.tool.c.linker.option.redirectoutput.629734526" name="Redirect diagnostics output to file (--list)" superClass="com.arm.tool.c.linker.option.redirectoutput" value="sample_threadx.map" valueType="string"/> + <option id="com.arm.tool.c.linker.option.libsearch.747365095" name="User library search path (--userlibpath)" superClass="com.arm.tool.c.linker.option.libsearch"/> + <option id="com.arm.tool.c.linker.libs.2121493259" name="User library files" superClass="com.arm.tool.c.linker.libs" valueType="libs"> + <listOptionValue builtIn="false" value="..\..\tx\Debug\tx.a"/> + </option> + <option id="com.arm.tool.c.linker.option.flags.1576883448" name="Other flags" superClass="com.arm.tool.c.linker.option.flags" valueType="stringList"/> + </tool> + <tool id="com.arm.tool.librarian.v6.1090597542" name="ARM Librarian 6" superClass="com.arm.tool.librarian.v6"/> + </toolChain> + </folderInfo> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + <cconfiguration id="com.arm.eclipse.build.config.v6.exe.release.1970372372"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.release.1970372372" 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"/> + <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.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.release.1970372372" name="Release" parent="com.arm.eclipse.build.config.v6.exe.release"> + <folderInfo id="com.arm.eclipse.build.config.v6.exe.release.1970372372." name="/" resourcePath=""> + <toolChain id="com.arm.toolchain.v6.exe.release.1208724479" name="ARM Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.release"> + <targetPlatform id="com.arm.eclipse.build.config.v6.exe.release.1970372372..306578502" name=""/> + <builder buildPath="${workspace_loc:/sample_threadx}/Release" id="com.arm.toolchain.v6.builder.1599248707" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/> + <tool id="com.arm.tool.c.compiler.v6.117703562" name="ARM C Compiler 6" superClass="com.arm.tool.c.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.high" id="com.arm.tool.c.compiler.v6.base.option.optlevel.1549626078" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.tool.c.compiler.v6.base.options.debug.level.109227440" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" valueType="enumerated"/> + <inputType id="com.arm.tool.c.compiler.v6.base.input.1407956082" superClass="com.arm.tool.c.compiler.v6.base.input"/> + <inputType id="com.arm.tool.cpp.compiler.v6.base.input.1636042802" superClass="com.arm.tool.cpp.compiler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.cpp.compiler.v6.1755515797" name="ARM C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.high" id="com.arm.tool.c.compiler.v6.base.option.optlevel.1001199458" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.tool.c.compiler.v6.base.options.debug.level.1882852746" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/> + </tool> + <tool id="com.arm.tool.assembler.v6.759015076" name="ARM Assembler 6" superClass="com.arm.tool.assembler.v6"> + <option defaultValue="com.arm.tool.assembler.v6.base.options.debug.level.none" id="com.arm.tool.assembler.v6.base.options.debug.level.1943766996" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/> + <inputType id="com.arm.tool.assembler.v6.base.input.385905318" superClass="com.arm.tool.assembler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.c.linker.v6.1686707697" name="ARM Linker 6" superClass="com.arm.tool.c.linker.v6"/> + <tool id="com.arm.tool.librarian.v6.1878811431" name="ARM Librarian 6" superClass="com.arm.tool.librarian.v6"/> + </toolChain> + </folderInfo> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <project id="sample_threadx.com.arm.eclipse.build.project.v6.exe.1027551600" name="Executable" projectType="com.arm.eclipse.build.project.v6.exe"/> + </storageModule> + <storageModule moduleId="scannerConfiguration"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> + <storageModule moduleId="refreshScope" versionNumber="2"> + <configuration configurationName="Debug"> + <resource resourceType="PROJECT" workspacePath="/sample_threadx"/> + </configuration> + <configuration configurationName="Release"> + <resource resourceType="PROJECT" workspacePath="/sample_threadx"/> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> +</cproject> diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/.project b/ports/cortex_a5x/ac6/example_build/sample_threadx/.project new file mode 100644 index 00000000..a1b15572 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/.project @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>sample_threadx</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> + <triggers>clean,full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.cdt.core.cnature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> + </natures> +</projectDescription> diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/.settings/language.settings.xml b/ports/cortex_a5x/ac6/example_build/sample_threadx/.settings/language.settings.xml new file mode 100644 index 00000000..dd0920bb --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/.settings/language.settings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<project> + <configuration id="com.arm.eclipse.build.config.v6.exe.debug.1756493040" name="Debug"> + <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> + <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> + <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> + <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> + <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-294697026837367808" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="ARM Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <language-scope id="org.eclipse.cdt.core.gcc"/> + <language-scope id="org.eclipse.cdt.core.g++"/> + </provider> + </extension> + </configuration> + <configuration id="com.arm.eclipse.build.config.v6.exe.release.1970372372" name="Release"> + <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> + <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> + <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> + <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> + <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-264130677454984672" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="ARM Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <language-scope id="org.eclipse.cdt.core.gcc"/> + <language-scope id="org.eclipse.cdt.core.g++"/> + </provider> + </extension> + </configuration> +</project> diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.S b/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.S new file mode 100644 index 00000000..aaf0f7f8 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.S @@ -0,0 +1,431 @@ +// ------------------------------------------------------------ +// ARMv8-A AArch64 Generic Timer Access Functions +// +// Copyright ARM Ltd 2013. All rights reserved. +// ------------------------------------------------------------ + + + .section AArch64_GenericTimer,"ax" + .align 3 + +// ------------------------------------------------------------ + + .global getCNTFRQ + // uint32_t getCNTFRQ(void) + // Returns the value of CNTFRQ_EL0 + .type getCNTFRQ, @function +getCNTFRQ: + MRS x0, CNTFRQ_EL0 + RET + + +// ------------------------------------------------------------ + + .global setCNTFRQ + // void setCNTFRQ(uint32_t freq) + // Sets the value of CNTFRQ_EL0 (only possible at EL3) + // w0 - freq - The value to be written into CNTFRQ_EL0 + .type setCNTFRQ, @function +setCNTFRQ: + MSR CNTFRQ_EL0, x0 + RET + + +// ------------------------------------------------------------ + + .global getPhysicalCount + // uint64_t getPhysicalCount(void) + // Returns the current value of physical count (CNTPCT_EL0) + .type getPhysicalCount, @function +getPhysicalCount: + MRS x0, CNTPCT_EL0 + RET + + +// ------------------------------------------------------------ + + .global getVirtualCount + // uint64_t getVirtualCount(void) + // Returns the current value of the virtual count register (CNTVCT_EL0) + .type getVirtualCount, @function +getVirtualCount: + MRS x0, CNTVCT_EL0 + RET + + +// ------------------------------------------------------------ + + .global getEL1Ctrl + // uint32_t getEL1Ctrl(void) + // Returns the value of EL1 Timer Control Register (CNTKCTL_EL1) + .type getEL1Ctrl, @function +getEL1Ctrl: + MRS x0, CNTKCTL_EL1 + RET + + +// ------------------------------------------------------------ + + .global setEL1Ctrl + // void setEL1Ctrl(uint32_t value) + // Sets the value of Counter Non-secure EL1 Control Register (CNTKCTL_EL1) + // 0 - value - The value to be written into CNTKCTL_EL1 + .type setEL1Ctrl, @function +setEL1Ctrl: + MSR CNTKCTL_EL1, x0 + RET + + +// ------------------------------------------------------------ + + .global getEL2Ctrl + // uint32_t getEL2Ctrl(void) + // Returns the value of the EL2 Timer Control Register (CNTHCTL_EL2) + .type getEL2Ctrl, @function +getEL2Ctrl: + MRS x0, CNTHCTL_EL2 + RET + + +// ------------------------------------------------------------ + + .global setEL2Ctrl + // void setEL2Ctrl(uint32_t value) + // Sets the value of the EL2 Timer Control Register (CNTHCTL_EL2) + // x0 - value - The value to be written into CNTHCTL_EL2 + .type setEL2Ctrl, @function +setEL2Ctrl: + MSR CNTHCTL_EL2, x0 + RET + + +// ------------------------------------------------------------ +// Non-Secure Physical Timer +// ------------------------------------------------------------ + + .global getNSEL1PhysicalCompValue + // uint64_t getNSEL1PhysicalCompValue(void) + // Returns the value of Non-Secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) + .type getNSEL1PhysicalCompValue, @function +getNSEL1PhysicalCompValue: + MRS x0, CNTP_CVAL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setNSEL1PhysicalCompValue + // void setNSEL1PhysicalCompValue(uint64_t value) + // Sets the value of the Non-Secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) + // x0 - value - The value to be written into CNTP_CVAL_EL0 + .type setNSEL1PhysicalCompValue, @function +setNSEL1PhysicalCompValue: + MSR CNTP_CVAL_EL0, x0 + RET + + +// ------------------------------------------------------------ + + .global getNSEL1PhysicalTimerValue + // uint32_t getNSEL1PhysicalTimerValue(void) + // Returns the value of Non-Secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) + .type getNSEL1PhysicalTimerValue, @function +getNSEL1PhysicalTimerValue: + MRS x0, CNTP_TVAL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setNSEL1PhysicalTimerValue + // void setNSEL1PhysicalTimerValue(uint32_t value) + // Sets the value of the Non-Secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) + // w0 - value - The value to be written into CNTP_TVAL_EL0 + .type setNSEL1PhysicalTimerValue, @function +setNSEL1PhysicalTimerValue: + MSR CNTP_TVAL_EL0, x0 + RET + + +// ------------------------------------------------------------ + + .global getNSEL1PhysicalTimerCtrl + // uint32_t getNSEL1PhysicalTimerCtrl(void) + // Returns the value of Non-Secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) + .type getNSEL1PhysicalTimerCtrl, @function +getNSEL1PhysicalTimerCtrl: + MRS x0, CNTP_CTL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setNSEL1PhysicalTimerCtrl + // void setNSEL1PhysicalTimerCtrl(uint32_t value) + // Sets the value of the Non-Secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) + // w0 - value - The value to be written into CNTP_CTL_EL0 + .type setNSEL1PhysicalTimerCtrl, @function +setNSEL1PhysicalTimerCtrl: + MSR CNTP_CTL_EL0, x0 + RET + + +// ------------------------------------------------------------ +// Secure Physical Timer +// ------------------------------------------------------------ + + .global getSEL1PhysicalCompValue + // uint64_t getSEL1PhysicalCompValue(void) + // Returns the value of Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) + .type getSEL1PhysicalCompValue, @function +getSEL1PhysicalCompValue: + MRS x0, CNTPS_CVAL_EL1 + RET + + +// ------------------------------------------------------------ + + .global setSEL1PhysicalCompValue + // void setSEL1PhysicalCompValue(uint64_t value) + // Sets the value of the Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) + // x0 - value - The value to be written into CNTPS_CVAL_EL1 + .type setSEL1PhysicalCompValue, @function +setSEL1PhysicalCompValue: + MSR CNTPS_CVAL_EL1, x0 + RET + + + +// ------------------------------------------------------------ + + .global getSEL1PhysicalTimerValue + // uint32_t getSEL1PhysicalTimerValue(void) + // Returns the value of Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) + .type getSEL1PhysicalTimerValue, @function +getSEL1PhysicalTimerValue: + MRS x0, CNTPS_TVAL_EL1 + RET + + +// ------------------------------------------------------------ + + .global setSEL1PhysicalTimerValue + // void setSEL1PhysicalTimerValue(uint32_t value) + // Sets the value of the Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) + // w0 - value - The value to be written into CNTPS_TVAL_EL1 + .type setSEL1PhysicalTimerValue, @function +setSEL1PhysicalTimerValue: + MSR CNTPS_TVAL_EL1, x0 + RET + + +// ------------------------------------------------------------ + + .global getSEL1PhysicalTimerCtrl + // uint32_t getSEL1PhysicalTimerCtrl(void) + // Returns the value of Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) + .type getSEL1PhysicalTimerCtrl, @function +getSEL1PhysicalTimerCtrl: + MRS x0, CNTPS_CTL_EL1 + RET + + +// ------------------------------------------------------------ + + .global setSEL1PhysicalTimerCtrl + // void setSEL1PhysicalTimerCtrl(uint32_t value) + // Sets the value of the Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) + // w0 - value - The value to be written into CNTPS_CTL_EL1 + .type setSEL1PhysicalTimerCtrl, @function +setSEL1PhysicalTimerCtrl: + MSR CNTPS_CTL_EL1, x0 + RET + + +// ------------------------------------------------------------ + + .global configSecureEL1TimerAccess + // void configSecureEL1TimerAccess(unsigned int config)// + // Sets the values of the SCR_EL3.ST bit (bit 11) based on the value in x0 + // EL3 accessible only! + .type configSecureEL1TimerAccess, @function +configSecureEL1TimerAccess: + MRS x1, SCR_EL3 + BFI x1, x0, #11, #1 + MSR SCR_EL3, x1 + RET + + +// ------------------------------------------------------------ +// Virtual Timer +// ------------------------------------------------------------ + + .global getEL1VirtualCompValue + // uint64_t getEL1VirtualCompValue(void) + // Returns the value of EL1 Virtual Compare Value Register (CNTV_CVAL_EL0) + .type getEL1VirtualCompValue, @function +getEL1VirtualCompValue: + MRS x0, CNTV_CVAL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setEL1VirtualCompValue + // void setEL1VirtualCompValue(uint64_t value) + // Sets the value of the EL1 Virtual Compare Value Register (CNTV_CVAL_EL0) + // x0 - value - The value to be written into CNTV_CVAL_EL0 + .type setEL1VirtualCompValue, @function +setEL1VirtualCompValue: + MSR CNTV_CVAL_EL0, x0 + RET + + +// ------------------------------------------------------------ + + .global getEL1VirtualTimerValue + // uint32_t getEL1VirtualTimerValue(void) + // Returns the value of EL1 Virtual Timer Value Register (CNTV_TVAL_EL0) + .type getEL1VirtualTimerValue, @function +getEL1VirtualTimerValue: + MRS x0, CNTV_TVAL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setEL1VirtualTimerValue + // void setEL1VirtualTimerValue(uint32_t value) + // Sets the value of the EL1 Virtual Timer Value Register (CNTV_TVAL_EL0) + // w0 - value - The value to be written into CNTV_TVAL_EL0 + .type setEL1VirtualTimerValue, @function +setEL1VirtualTimerValue: + MSR CNTV_TVAL_EL0, x0 + RET + + +// ------------------------------------------------------------ + + .global getEL1VirtualTimerCtrl + // uint32_t getEL1VirtualTimerCtrl(void) + // Returns the value of EL1 Virtual Timer Control Register (CNTV_CTL_EL0) + .type getEL1VirtualTimerCtrl, @function +getEL1VirtualTimerCtrl: + MRS x0, CNTV_CTL_EL0 + RET + + +// ------------------------------------------------------------ + + .global setEL1VirtualTimerCtrl + // void setEL1VirtualTimerCtrl(uint32_t value) + // Sets the value of the EL1 Virtual Timer Control Register (CNTV_CTL_EL0) + // w0 - value - The value to be written into CNTV_CTL_EL0 + .type setEL1VirtualTimerCtrl, @function +setEL1VirtualTimerCtrl: + MSR CNTV_CTL_EL0, x0 + RET + + +// ------------------------------------------------------------ +// Virtual Timer functions to be called by EL2 +// ------------------------------------------------------------ + + .global getVirtualCounterOffset + // uint64_t getVirtualCounterOffset(void) + // Returns the value of the Counter Virtual Offset Register (CNTVOFF_EL2) + // EL2 and EL3 only + .type getVirtualCounterOffset, @function +getVirtualCounterOffset: + MRS x0, CNTVOFF_EL2 + RET + + +// ------------------------------------------------------------ + + .global setVirtualCounterOffset + // void setVirtualCounterOffset(uint64_t offset) + // Sets the value of the Counter Virtual Offset Register (CNTVOFF_EL2) + // x0 - offset - The value to be written into CNTVOFF_EL2 + // EL2 and EL3 only + .type setVirtualCounterOffset, @function +setVirtualCounterOffset: + MSR CNTVOFF_EL2, x0 + RET + + +// ------------------------------------------------------------ +// EL2 Physical Timer +// ------------------------------------------------------------ + + .global getEL2PhysicalCompValue + // uint64_t getEL2PhysicalCompValue(void) + // Returns the value of EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) + .type getEL2PhysicalCompValue, @function +getEL2PhysicalCompValue: + MRS x0, CNTHP_CVAL_EL2 + RET + + +// ------------------------------------------------------------ + + .global setEL2PhysicalCompValue + // void setEL2PhysicalCompValue(uint64_t value) + // Sets the value of the EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) + // x0 - value - The value to be written into CNTHP_CVAL_EL2 + .type setEL2PhysicalCompValue, @function +setEL2PhysicalCompValue: + MSR CNTHP_CVAL_EL2, x0 + RET + + + +// ------------------------------------------------------------ + + .global getEL2PhysicalTimerValue + // uint32_t getEL2PhysicalTimerValue(void) + // Returns the value of EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) + .type getEL2PhysicalTimerValue, @function +getEL2PhysicalTimerValue: + MRS x0, CNTHP_TVAL_EL2 + RET + + +// ------------------------------------------------------------ + + .global setEL2PhysicalTimerValue + // void setEL2PhysicalTimerValue(uint32_t value) + // Sets the value of the EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) + // w0 - value - The value to be written into CNTHP_TVAL_EL2 + .type setEL2PhysicalTimerValue, @function +setEL2PhysicalTimerValue: + MSR CNTHP_TVAL_EL2, x0 + RET + + +// ------------------------------------------------------------ + + .global getEL2PhysicalTimerCtrl + // uint32_t getEL2PhysicalTimerCtrl(void) + // Returns the value of EL2 Physical Timer Control Register (CNTHP_CTL_EL2) + .type getEL2PhysicalTimerCtrl, @function +getEL2PhysicalTimerCtrl: + MRS x0, CNTHP_CTL_EL2 + RET + + +// ------------------------------------------------------------ + + .global setEL2PhysicalTimerCtrl + // void setEL2PhysicalTimerCtrl(uint32_t value) + // Sets the value of the EL2 Physical Timer Control Register (CNTHP_CTL_EL2) + // w0 - value - The value to be written into CNTHP_CTL_EL2 + .type setEL2PhysicalTimerCtrl, @function +setEL2PhysicalTimerCtrl: + MSR CNTHP_CTL_EL2, x0 + RET + + +// ------------------------------------------------------------ +// End of code +// ------------------------------------------------------------ diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.h b/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.h new file mode 100644 index 00000000..63474ac8 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/armv8_aarch64_SystemTimer.h @@ -0,0 +1,206 @@ +// ------------------------------------------------------------ +// ARMv8-A AArch64 System Timer +// Header Filer +// +// Copyright ARM Ltd 2013. All rights reserved. +// ------------------------------------------------------------ + +#ifndef _ARMV8A_SYSTEM_TIMER_H +#define _ARMV8A_SYSTEM_TIMER_H + +// ------------------------------------------------------------ +// CNTFRQ holds the frequency of the system counter +// Readable in all ELs +// Writable only by EL3 + +// Returns the value of CNTFRQ_EL0 +unsigned int getCNTFRQ(void); + +// Sets the value of CNTFRQ_EL0 (EL3 only!) +// freq - The value to be written into CNTFRQ_EL3 +void setCNTFRQ(unsigned int freq); + +// ------------------------------------------------------------ +// CNTPCT_EL0 and CNTVCT_EL0 hold the physical and virtual counts +// Always accessable in Hpy and Secure EL1 +// Access from EL2 and Non-Secure EL1 is configurable + +// Returns the current value of physical count (CNTPCT_EL0) +unsigned long long getPhysicalCount(void); + +// Returns the current value of the virtual count register (CNTVCT_EL0) +unsigned long long getVirtualCount(void); + +// ------------------------------------------------------------ +// The CNTKCTL register controls whether CNTPCT can be accessed from EL0 +// Only acceable from EL1 and EL2 + +#define CNTKCTL_PCTEN (1 << 0) // Controls whether the physical counter, CNTPCT, and the frequency register CNTFRQ, are accessible from EL0 +#define CNTKCTL_VCTEN (1 << 1) // Controls whether the virtual counter, CNTVCT, and the frequency register CNTFRQ, are accessible from +#define CNTKCTL_EVNTEN (1 << 2) // Enables the generation of an event stream from the virtual counter +#define CNTKCTL_EVNTDIR (1 << 3) // Controls which transition of the CNTVCT trigger bit, defined by EVNTI, generates an event + +// Returns the value of EL1 Timer Control Register (CNTKCTL_EL1) +unsigned int getEL1Ctrl(void); + +// Sets the value of EL1 Timer Control Register (CNTKCTL_EL1) +// value - The value to be written into CNTKCTL_EL1 +void setEL1Ctrl(unsigned int value); + +// ------------------------------------------------------------ +// The CNTHCTL_EL2 register controls whether CNTPCT_EL0 can be accessed from EL1 +// Only accessable from EL2 and EL3 + +#define CNTHCTL_CNTPCT (1 << 0) +#define CNTHCTL_EVNTEN (1 << 2) +#define CNTHCTL_EVNTDIR (1 << 3) + +// Returns the value of the EL2 Timer Control Register (CNTHCTL_EL2) +unsigned int getEL2Ctrl(void); + +// Sets the value of EL2 Timer Control Register (CNTHCTL_EL2) +// value - The value to be written into CNTHCTL_EL2 +void setEL2Ctrl(unsigned int value); + +// ------------------------------------------------------------ +// Non-Secure Physical Timer +// ------------------------------------------------------------ +// Accessible from EL3, EL2 and EL1 + +// Returns the value of Non-Secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) +unsigned long long getNSEL1PhysicalCompValue(void); + +// Sets the value of the Non-Secure EL1 Physical Compare Value Register (CNTP_CVAL_EL0) +// value - The value to be written into CNTP_CVAL_EL0 +void setNSEL1PhysicalCompValue(unsigned long long value); + +// Returns the value of Non-Secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) +unsigned int getNSEL1PhysicalTimerValue(void); + +// Sets the value of the Non-Secure EL1 Physical Timer Value Register (CNTP_TVAL_EL0) +// value - The value to be written into CNTP_TVAL_EL0 +void setNSEL1PhysicalTimerValue(unsigned int value); + +#define CNTP_CTL_ENABLE (1 << 0) +#define CNTP_CTL_MASK (1 << 1) +#define CNTP_CTL_STATUS (1 << 2) + +// Returns the value of Non-Secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) +unsigned int getNSEL1PhysicalTimerCtrl(void); + +// Sets the value of the Non-Secure EL1 Physical Timer Control Register (CNTP_CTL_EL0) +// value - The value to be written into CNTP_CTL_EL0 +void setNSEL1PhysicalTimerCtrl(unsigned int value); + +// ------------------------------------------------------------ +// Secure Physical Timer +// ------------------------------------------------------------ +// Accessible from EL3, and configurably from secure EL1 + +// Returns the value of Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) +unsigned long long getSEL1PhysicalCompValue(void); + +// Sets the value of the Secure EL1 Physical Compare Value Register (CNTPS_CVAL_EL1) +// value - The value to be written into CNTPS_CVAL_EL1 +void setSEL1PhysicalCompValue(unsigned long long value); + +// Returns the value of Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) +unsigned int getSEL1PhysicalTimerValue(void); + +// Sets the value of the Secure EL1 Physical Timer Value Register (CNTPS_TVAL_EL1) +// value - The value to be written into CNTPS_TVAL_EL1 +void setSEL1PhysicalTimerValue(unsigned int value); + +#define CNTPS_CTL_ENABLE (1 << 0) +#define CNTPS_CTL_MASK (1 << 1) +#define CNTPS_CTL_STATUS (1 << 2) + +// Returns the value of Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) +unsigned int getSEL1PhysicalTimerCtrl(void); + +// Sets the value of the Secure EL1 Physical Timer Control Register (CNTPS_CTL_EL1) +// value - The value to be written into CNTPS_CTL_EL1 +void setSEL1PhysicalTimerCtrl(unsigned int value); + +// The SCR_EL3 register controls whether CNTPS_TVAL_EL1, +// CNTPS_CTL_EL1, and CNTPS_CVAL_EL1 can be accessed by secure +// EL1. +// Only accessible from EL3 + +#define SCR_ENABLE_SECURE_EL1_ACCESS (1) +#define SCR_DISABLE_SECURE_EL1_ACCESS (0) + +// Sets the values of the SCR_EL3.ST bit (bit 11) based on the value passed in 'config' +void configSecureEL1TimerAccess(unsigned int config); + +// ------------------------------------------------------------ +// Virtual Timer +// ------------------------------------------------------------ +// Accessible from Non-Secure EL1 and EL2 + +// Returns the value of EL1 Virtual Compare Value Register (CNTV_CVAL) +unsigned long long getEL1VirtualCompValue(void); + +// Sets the value of the EL1 Virtual Compare Value Register (CNTV_CVAL) +// value - The value to be written into CNTV_CVAL +void setEL1VirtualCompValue(unsigned long long value); + +// Returns the value of EL1 Virtual Timer Value Register (CNTV_TVAL) +unsigned int getEL1VirtualTimerValue(void); + +// Sets the value of the EL1 Virtual Timer Value Register (CNTV_TVAL) +// value - The value to be written into CNTV_TVAL +void setEL1VirtualTimerValue(unsigned int value); + +#define CNTV_CTL_ENABLE (1 << 0) +#define CNTV_CTL_MASK (1 << 1) +#define CNTV_CTL_STATUS (1 << 2) + +// Returns the value of EL1 Virtual Timer Control Register (CNTV_CTL) +unsigned int getEL1VirtualTimerCtrl(void); + +// Sets the value of the EL1 Virtual Timer Control Register (CNTV_CTL) +// value - The value to be written into CNTV_CTL +void setEL1VirtualTimerCtrl(unsigned int value); + +// +// Virtual timer functions to be called by EL2 +// + +// CNTVCT_EL2 holds the offset the virtual count is from the physical count +// Only accessable from EL2 and EL3 + +// Returns the value of the Counter Virtual Offset Register (CNTVOFF_EL2) +unsigned long long getVirtualCounterOffset(void); + +// Sets the value of the Counter Virtual Offset Register (CNTVOFF_EL2) +// offset - The value to be written into CNTVOFF_EL2 +void setVirtualCounterOffset(unsigned long long offset); + +// ------------------------------------------------------------ +// Hypervisor (EL2) Timer +// ------------------------------------------------------------ + +// Returns the value of EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) +unsigned long long getEL2PhysicalCompValue(void); + +// Sets the value of the EL2 Physical Compare Value Register (CNTHP_CVAL_EL2) +// value - The value to be written into CNTHP_CVAL_EL2 +void setEL2PhysicalCompValue(unsigned long long value); + +// Returns the value of EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) +unsigned int getEL2PhysicalTimerValue(void); + +#define CNTHP_CTL_ENABLE (1 << 0) +#define CNTHP_CTL_MASK (1 << 1) +#define CNTHP_CTL_STATUS (1 << 2) + +// Sets the value of the EL2 Physical Timer Value Register (CNTHP_TVAL_EL2) +// value - The value to be written into CNTHP_TVAL_EL2 +void setEL2PhysicalTimerValue(unsigned int value); + +#endif + +// ------------------------------------------------------------ +// End of armv8_aarch64_SystemTimer.h +// ------------------------------------------------------------ diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/el3_vectors.S b/ports/cortex_a5x/ac6/example_build/sample_threadx/el3_vectors.S new file mode 100644 index 00000000..7f4effe7 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/el3_vectors.S @@ -0,0 +1,138 @@ +// ------------------------------------------------------------ +// Exceptions workbook exercise +// +// Copyright ARM LTD, 2012 +// ------------------------------------------------------------ + + .section VECTORS,"ax" + .align 12 + + + .global el3_vectors +el3_vectors: + + .global fiqHandler + .global irqHandler + +// ------------------------------------------------------------ +// Current EL with SP0 +// ------------------------------------------------------------ + .balign 128 +sync_current_el_sp0: + B . // Synchronous + + .balign 128 +irq_current_el_sp0: + B irqFirstLevelHandler // IRQ + + .balign 128 +fiq_current_el_sp0: + B fiqFirstLevelHandler // FIQ + + .balign 128 +serror_current_el_sp0: + B . // SError + +// ------------------------------------------------------------ +// Current EL with SPx +// ------------------------------------------------------------ + + .balign 128 +sync_current_el_spx: + B . // Synchronous + + .balign 128 +irq_current_el_spx: + B irqFirstLevelHandler // IRQ + + .balign 128 +fiq_current_el_spx: + B fiqFirstLevelHandler // FIQ + + .balign 128 +serror_current_el_spx: + B . // SError + +// ------------------------------------------------------------ +// Lower EL using AArch64 +// ------------------------------------------------------------ + + .balign 128 +sync_lower_el_aarch64: + B . + + .balign 128 +irq_lower_el_aarch64: + B irqFirstLevelHandler // IRQ + + .balign 128 +fiq_lower_el_aarch64: + B fiqFirstLevelHandler // FIQ + + .balign 128 +serror_lower_el_aarch64: + B . // SError + +// ------------------------------------------------------------ +// Lower EL using AArch32 +// ------------------------------------------------------------ + + .balign 128 +sync_lower_el_aarch32: + B . + + .balign 128 +irq_lower_el_aarch32: + B irqFirstLevelHandler // IRQ + + .balign 128 +fiq_lower_el_aarch32: + B fiqFirstLevelHandler // FIQ + + .balign 128 +serror_lower_el_aarch32: + B . // SError + + +// ------------------------------------------------------------ + +irqFirstLevelHandler: + STP x29, x30, [sp, #-16]! + BL _tx_thread_context_save + + BL irqHandler + + B _tx_thread_context_restore + +fiqFirstLevelHandler: + STP x29, x30, [sp, #-16]! + STP x18, x19, [sp, #-16]! + STP x16, x17, [sp, #-16]! + STP x14, x15, [sp, #-16]! + STP x12, x13, [sp, #-16]! + STP x10, x11, [sp, #-16]! + STP x8, x9, [sp, #-16]! + STP x6, x7, [sp, #-16]! + STP x4, x5, [sp, #-16]! + STP x2, x3, [sp, #-16]! + STP x0, x1, [sp, #-16]! + + BL fiqHandler + + LDP x0, x1, [sp], #16 + LDP x2, x3, [sp], #16 + LDP x4, x5, [sp], #16 + LDP x6, x7, [sp], #16 + LDP x8, x9, [sp], #16 + LDP x10, x11, [sp], #16 + LDP x12, x13, [sp], #16 + LDP x14, x15, [sp], #16 + LDP x16, x17, [sp], #16 + LDP x18, x19, [sp], #16 + LDP x29, x30, [sp], #16 + ERET + +// ------------------------------------------------------------ +// End of file +// ------------------------------------------------------------ + diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c new file mode 100644 index 00000000..1ecd5f33 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.c @@ -0,0 +1,419 @@ +// ---------------------------------------------------------- +// GIC400 - Generic Interrupt Controller +// +// GIC Exercise +// ---------------------------------------------------------- + +#include "gic400_gic.h" + +struct gic400_dist_if +{ + volatile unsigned int GICD_CTLR; // +0x000 - RW - Distributor Control Register + const volatile unsigned int GICD_TYPRE; // +0x004 - RO - Interrupt Controller Type Register + const volatile unsigned int GICD_IIDR; // +0x008 - RO - Distributor Implementer Identification Register + + const volatile unsigned int padding0[29]; + + volatile unsigned int GICD_IGROUPR[32]; // +0x080 - RW - Interrupt Groupt Registers (Security Registers in GICv1) + + volatile unsigned int GICD_ISENABLER[32]; // +0x100 - RW - Interrupt Set-Enable Registers + volatile unsigned int GICD_ICENABLER[32]; // +0x180 - RW - Interrupt Clear-Enable Registers + volatile unsigned int GICD_ISPENDR[32]; // +0x200 - RW - Interrupt Set-Pending Registers + volatile unsigned int GICD_ICPENDR[32]; // +0x280 - RW - Interrupt Clear-Pending Registers + volatile unsigned int GICD_ISACTIVER[32]; // +0x300 - RW - Interrupt Set-Active Register + volatile unsigned int GICD_ICACTIVER[32]; // +0x380 - RW - Interrupt Clear-Active Register + + volatile unsigned char GICD_IPRIORITYR[1024]; // +0x400 - RW - Interrupt Priority Registers + volatile unsigned int GICD_ITARGETSR[256]; // +0x800 - RW - Interrupt Processor Targets Registers + volatile unsigned int GICD_ICFGR[64]; // +0xC00 - RW - Interrupt Configuration Registers + + const volatile unsigned int padding2[128]; + + volatile unsigned int GICD_SGIR; // +0xF00 - WO - Software Generated Interrupt Register + +}; + +struct gic400_physical_cpu_if +{ + volatile unsigned int GICC_CTLR; // +0x000 - RW - CPU Interface Control Register + volatile unsigned int GICC_PMR; // +0x004 - RW - Interrupt Priority Mask Register + volatile unsigned int GICC_BPR; // +0x008 - RW - Binary Point Register + const volatile unsigned int GICC_IAR; // +0x00C - RO - Interrupt Acknowledge Register + volatile unsigned int GICC_EOIR; // +0x010 - WO - End of Interrupt Register + const volatile unsigned int GICC_RPR; // +0x014 - RO - Running Priority Register + const volatile unsigned int GICC_HPPIR; // +0x018 - RO - Highest Pending Interrupt Register + volatile unsigned int GICC_ABPR; // +0x01C - RW - Aliased Binary Point Register + const volatile unsigned int GICC_AIAR; // +0x020 - RO - Aliased Interrupt Acknowledge Register + volatile unsigned int GICC_AEOIR; // +0x024 - WO - Aliased End of Interrupt Register + const volatile unsigned int GICC_AHPPIR; // +0x028 - RO - Aliased Highest Pending Interrupt Register + + const volatile unsigned int padding0[52]; + + const volatile unsigned int GICC_IIDR; // +0x0FC - RO - CPU Interface Identification Register +}; + +struct gic400_dist_if* gic_dist; +struct gic400_physical_cpu_if* gic_cpu; + + +// ------------------------------------------------------------ + +void setGICAddr(void* dist, void* cpu) +{ + gic_dist = (struct gic400_dist_if*)dist; + gic_cpu = (struct gic400_physical_cpu_if*)cpu; + return; +} + +// ------------------------------------------------------------ + +// Global enable of the Interrupt Distributor +void enableGIC(void) +{ + gic_dist->GICD_CTLR = 3; + return; +} + +// Global disable of the Interrupt Distributor +void disableGIC(void) +{ + gic_dist->GICD_CTLR = 0; + return; +} + +// ------------------------------------------------------------ + +// Enables the interrupt source number ID +void enableIntID(unsigned int ID) +{ + unsigned int bank; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + + gic_dist->GICD_ISENABLER[bank] = ID; + + return; +} + +// Disables the interrupt source number ID +void disableIntID(unsigned int ID) +{ + unsigned int bank; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + + gic_dist->GICD_ICENABLER[bank] = ID; + + return; +} + +// ------------------------------------------------------------ + +// Sets the priority of the specified ID +void setIntPriority(unsigned int ID, unsigned int priority) +{ + if (ID > 1020) // Check ID in range + return; + + // The priority registers allows byte accesses + // meaning using a char array we can directly + // reference the correct entry + gic_dist->GICD_IPRIORITYR[ID] = priority; + + return; +} + +// Returns the priority of the specified ID +unsigned int getIntPriority(unsigned int ID) +{ + if (ID > 1020) // Check ID in range + return 0; + + return gic_dist->GICD_IPRIORITYR[ID]; +} + +// ------------------------------------------------------------ + +// Sets the target CPUs of the specified ID +// For 'target' use one of the above defines +void setIntTarget(unsigned int ID, unsigned int target) +{ + unsigned int bank, tmp; + + target = target & 0xFF; // Target field is 8-bits, mask off unused bit + bank = ID/4; // There are 4 IDs per register, need to work out which register to access + ID = ID & 0x3; // ... and which field within the register + ID = ID * 8; // Convert from which field to a bit offset (8-bits per field) + + target = target << ID; // Move prioity value into correct bit position + + tmp = gic_dist->GICD_ITARGETSR[bank]; // Read the current value in the register + tmp = tmp & ~(0xFF << ID); // Blank out the field holding the value we're modifying + tmp = tmp | target; // OR in the new target + gic_dist->GICD_ITARGETSR[bank] = tmp; + + return; +} + +// Returns the target CPUs of the specified ID +unsigned int getIntTarget(unsigned int ID) +{ + unsigned int bank, tmp; + + bank = ID/4; // There are 4 IDs per register, need to work out which register to access + ID = ID & 0x3; // ... and which field within the register + ID = ID * 8; // Convert from which field to a bit offset (8-bits per field) + + tmp = gic_dist->GICD_ITARGETSR[bank]; + + tmp = tmp >> ID; // Shift desired field to bit position 0 + tmp = tmp & 0xFF; // Mask off the other bits + + return tmp; +} + +// ---------------------------------------------------------- + +// Configures the specified ID as being level or edge triggered +void configureSPI(unsigned int ID, unsigned int conf) +{ + unsigned int bank, tmp; + + conf = conf & 0x3; // Mask out unused bits + + bank = ID/16; // There are 16 IDs per register, need to work out which register to access + ID = ID & 0xF; // ... and which field within the register + ID = ID * 2; // Convert from which field to a bit offset (2-bits per field) + + conf = conf << ID; // Move configuration value into correct bit position + + tmp = gic_dist-> GICD_ICFGR[bank]; // Read current vlase + tmp = tmp & ~(0x3 << ID); // Clear the bits for the specified field + tmp = tmp | conf; // OR in new configuration + gic_dist-> GICD_ICFGR[bank] = tmp; // Write updated value back + + return; +} + +// ---------------------------------------------------------- + +// Sets the pending bit of the specified ID +void setIntPending(unsigned int ID) +{ + unsigned int bank; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + + gic_dist->GICD_ISPENDR[bank] = ID; + + return; +} + +// Clears the pending bit of the specified ID +void clearIntPending(unsigned int ID) +{ + unsigned int bank; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + + gic_dist->GICD_ICPENDR[bank] = ID; + + return; +} + +// Returns the value of the status bit of the specifed ID +unsigned int getIntPending(unsigned int ID) +{ + unsigned int bank, tmp; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + tmp = gic_dist->GICD_ICPENDR[bank]; // Read the register containing the ID we are interested in + tmp = tmp >> ID; // Shift the status bit for specified ID to position 0 + tmp = tmp & 0x1; // Mask off the rest of the register + + return tmp; +} + +// ------------------------------------------------------------ + +// Send a software generate interrupt +void sendSGI(unsigned int ID, unsigned int cpu_list, unsigned int filter_list, unsigned int SATT) +{ + // Ensure unused bits are clear, and shift into correct bit position + ID = ID & 0xF; + SATT = (SATT & 0x1) << 15; + cpu_list = (cpu_list & 0xFF) << 16; + filter_list = (filter_list & 0x3) << 24; + + // Combine fields + ID = ID | SATT | cpu_list | filter_list; + + gic_dist->GICD_SGIR = ID; + + return; +} + +// ------------------------------------------------------------ + +// Sets the specified ID as secure +void makeIntGroup0(unsigned int ID) +{ + unsigned int bank, tmp; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + ID = ~ID; // Invert to get mask + + tmp = gic_dist->GICD_IGROUPR[bank]; // Read current value + tmp = tmp & ID; + gic_dist->GICD_IGROUPR[bank] = tmp; + + return; +} + +// Set the specified ID as non-secure +void makeIntGroup1(unsigned int ID) +{ + unsigned int bank, tmp; + + bank = ID/32; // There are 32 IDs per register, need to work out which register to access + ID = ID & 0x1f; // ... and which bit within the register + + ID = 1 << ID; // Move a '1' into the correct bit position + + tmp = gic_dist->GICD_IGROUPR[bank]; // Read current value + tmp = tmp | ID; // Or with bit mask to set the bit + gic_dist->GICD_IGROUPR[bank] = tmp; // Write-back +} + +// Returns the security of the specified ID +unsigned int getIntGroup(unsigned int ID) +{ + // TBD + return 0; +} + +// ------------------------------------------------------------ +// CPU Interface functions +// ------------------------------------------------------------ + +// Enables the CPU interface +// Must been done one each core seperately +void enableCPUInterface(void) +{ + unsigned int tmp; + + tmp = gic_cpu->GICC_CTLR; + tmp = tmp | 0x1; // Set bit 0 + gic_cpu->GICC_CTLR = tmp; +} + +// Enables the group 1 (non-secure) CPU interface +// This function can only be called from the Secure world +// Must been done one each core seperately +void enableNonSecureCPUInterface(void) +{ + unsigned int tmp; + + tmp = gic_cpu->GICC_CTLR; + tmp = tmp | 0x2; // Set bit 1 + gic_cpu->GICC_CTLR = tmp; +} + +// Disables the processor interface +void disableCPUInterface(void) +{ + unsigned int tmp; + + tmp = gic_cpu->GICC_CTLR; + tmp = tmp & 0xFFFFFFFFE; // Clear bit 0 + gic_cpu->GICC_CTLR = tmp; +} + +// Enables the sending of secure interrupts as FIQs +void enableSecureFIQs(void) +{ + unsigned int tmp; + + tmp = gic_cpu->GICC_CTLR; + tmp = tmp | 0x8; // Set bit 3 + gic_cpu->GICC_CTLR = tmp; +} + +// Disables the sending of secure interrupts as FIQs +void disableSecureFIQs(void) +{ + unsigned int tmp; + + tmp = gic_cpu->GICC_CTLR; + tmp = tmp | 0xFFFFFFFF7; // Clear bit 3 + gic_cpu->GICC_CTLR = tmp; +} + +// Returns the value of the Interrupt Acknowledge Register +unsigned int readIntAck(void) +{ + return gic_cpu->GICC_IAR; +} + +// Writes ID to the End Of Interrupt register +void writeEOI(unsigned int ID) +{ + gic_cpu->GICC_EOIR = ID; + return; +} + +// Returns the value of the Aliased Interrupt Acknowledge Register +unsigned int readAliasedIntAck(void) +{ + return gic_cpu->GICC_AIAR; +} + +// Writes ID to the Aliased End Of Interrupt register +void writeAliasedEOI(unsigned int ID) +{ + gic_cpu->GICC_AEOIR = ID; + return; +} + +// Sets the Priority mask register for the core run on +// The reset value masks ALL interrupts! +void setPriorityMask(unsigned int priority) +{ + gic_cpu->GICC_PMR = (priority & 0xFF); + return; +} + +// Sets the Binary Point Register for the core run on +void setBinaryPoint(unsigned int priority) +{ + gic_cpu->GICC_BPR = (priority & 0xFF); + return; +} + +// Sets the Aliased Binary Point Register for the core run on +void setAliasedBinaryPoint(unsigned int priority) +{ + gic_cpu->GICC_ABPR = (priority & 0xFF); + return; +} + +// ------------------------------------------------------------ +// End of gic400_gic.c +// ------------------------------------------------------------ diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h new file mode 100644 index 00000000..aca064c3 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/gic400_gic.h @@ -0,0 +1,192 @@ +// ---------------------------------------------------------- +// GIC400 - Generic Interrupt Controller +// Header +// +// Martin Weidmann Dec 2011 +// ---------------------------------------------------------- + +#ifndef __gic400_gic_h +#define __gic400_gic_h + +#define GIC_GIC400_PPI0 (0) +#define GIC_GIC400_PPI1 (1) +#define GIC_GIC400_PPI2 (2) +#define GIC_GIC400_PPI3 (3) +#define GIC_GIC400_PPI4 (4) +#define GIC_GIC400_PPI5 (5) +#define GIC_GIC400_PPI6 (6) +#define GIC_GIC400_PPI7 (7) +#define GIC_GIC400_PPI8 (8) +#define GIC_GIC400_PPI9 (9) +#define GIC_GIC400_PPI10 (10) +#define GIC_GIC400_PPI11 (11) +#define GIC_GIC400_PPI12 (12) +#define GIC_GIC400_PPI13 (13) +#define GIC_GIC400_PPI14 (14) +#define GIC_GIC400_PPI15 (15) +#define GIC_GIC400_PPI16 (16) +#define GIC_GIC400_PPI17 (17) +#define GIC_GIC400_PPI18 (18) +#define GIC_GIC400_PPI19 (19) +#define GIC_GIC400_PPI20 (20) +#define GIC_GIC400_PPI21 (21) +#define GIC_GIC400_PPI22 (22) +#define GIC_GIC400_PPI23 (23) +#define GIC_GIC400_PPI24 (24) +#define GIC_GIC400_PPI25 (25) +#define GIC_GIC400_PPI26 (26) +#define GIC_GIC400_PPI27 (27) +#define GIC_GIC400_PPI28 (28) +#define GIC_GIC400_PPI29 (29) +#define GIC_GIC400_PPI30 (30) +#define GIC_GIC400_PPI31 (31) + +// ---------------------------------------------------------- + +// Sets the address of the GIC's distributor and CPU interfaces +void setGICAddr(void* dist, void* cpu); + +// ---------------------------------------------------------- + +// Global enable of the Interrupt Distributor +void enableGIC(void); + +// Global disable of the Interrupt Distributor +void disableGIC(void); + +// ---------------------------------------------------------- + +// Enables the interrupt source number ID +void enableIntID(unsigned int ID); + +// Disables the interrupt source number ID +void disableIntID(unsigned int ID); + +// ---------------------------------------------------------- + +// Sets the priority of the specified ID +void setIntPriority(unsigned int ID, unsigned int priority); + +// Returns the priority of the specified ID +unsigned int getIntPriority(unsigned int ID); + +// ---------------------------------------------------------- + +#define GIC_GIC400_TARGET_CPU0 (0x01) +#define GIC_GIC400_TARGET_CPU1 (0x02) +#define GIC_GIC400_TARGET_CPU2 (0x04) +#define GIC_GIC400_TARGET_CPU3 (0x08) +#define GIC_GIC400_TARGET_CPU4 (0x10) +#define GIC_GIC400_TARGET_CPU5 (0x20) +#define GIC_GIC400_TARGET_CPU6 (0x40) +#define GIC_GIC400_TARGET_CPU7 (0x80) + +// Sets the target CPUs of the specified ID +// For 'target' use one of the above defines +void setIntTarget(unsigned int ID, unsigned int target); + +// Returns the target CPUs of the specified ID +unsigned int getIntTarget(unsigned int ID); + +// ---------------------------------------------------------- + +#define GIC_GIC400_CONFIG_LEVEL (0) +#define GIC_GIC400_CONFIG_EDGE (2) + +// Configures the specified ID as being level or edge triggered + +void configureSPI(unsigned int ID, unsigned int conf); + +// ---------------------------------------------------------- + +// Sets the pending bit of the specified ID +void setIntPending(unsigned int ID); + +// Clears the pending bit of the specified ID +void clearIntPending(unsigned int ID); + +#define GIC_GIC400_PENDING_IS_SET (1) +#define GIC_GIC400_PENDING_IS_CLEAR (0) + +// Returns the value of the status bit of the specified ID +unsigned int getIntPending(unsigned int ID); + +// ---------------------------------------------------------- + +#define GIC_GIC400_SGI_SECURE (0) +#define GIC_GIC400_SGI_NONSECURE (1) +#define GIC_GIC400_SGI_FILTER_USE_LIST (0) +#define GIC_GIC400_SGI_FILTER_NOT_THIS_CPU (1) +#define GIC_GIC400_SGI_FILTER_THIS_CPU (2) +#define GIC_GIC400_SGI_CPU0 (0x01) +#define GIC_GIC400_SGI_CPU1 (0x02) +#define GIC_GIC400_SGI_CPU2 (0x04) +#define GIC_GIC400_SGI_CPU3 (0x08) +#define GIC_GIC400_SGI_CPU4 (0x10) +#define GIC_GIC400_SGI_CPU5 (0x20) +#define GIC_GIC400_SGI_CPU6 (0x40) +#define GIC_GIC400_SGI_CPU7 (0x80) + +// Send a software generate interrupt +void sendSGI(unsigned int ID, unsigned int cpu_list, unsigned int filter_list, unsigned int SATT); + +// ---------------------------------------------------------- + +// Sets the specified ID as secure +void makeIntGroup0(unsigned int ID); + +// Set the specified ID as non-secure +void makeIntGroup1(unsigned int ID); + +// Returns the security of the specified ID +unsigned int getIntGroup(unsigned int ID); + +// ------------------------------------------------------------ +// CPU Interface functions +// ------------------------------------------------------------ + +// Enables the processor interface +// Must been done one each core seperately +void enableCPUInterface(void); + +// Enables the group 1 (non-secure) CPU interface +// This function can only be called from the Secure world +// Must been done one each core seperately +void enableNonSecureCPUInterface(void); + +// Disables the processor interface +void disableCPUInterface(void); + +// Enables the sending of secure interrupts as FIQs +void enableSecureFIQs(void); + +// Disables the sending of secure interrupts as FIQs +void disableSecureFIQs(void); + +// Returns the value of the Interrupt Acknowledge Register +unsigned int readIntAck(void); + +// Writes ID to the End Of Interrupt register +void writeEOI(unsigned int ID); + +// Returns the value of the Aliased Interrupt Acknowledge Register +unsigned int readAliasedIntAck(void); + +// Writes ID to the Aliased End Of Interrupt register +void writeAliasedEOI(unsigned int ID); + +// Sets the Priority mask register for the core run on +// The reset value masks ALL interrupts! +void setPriorityMask(unsigned int priority); + +// Sets the Binary Point Register for the core run on +void setBinaryPoint(unsigned int priority); + +// Sets the Aliased Binary Point Register for the core run on +void setAliasedBinaryPoint(unsigned int priority); + +#endif + +// ---------------------------------------------------------- +// End of gic400_gic.h +// ---------------------------------------------------------- diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/hw_setup.c b/ports/cortex_a5x/ac6/example_build/sample_threadx/hw_setup.c new file mode 100644 index 00000000..dc19cd3b --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/hw_setup.c @@ -0,0 +1,104 @@ +// +// Copyright ARM LTD, 2013 + +#include <stdio.h> +#include "gic400_gic.h" +#include "armv8_aarch64_SystemTimer.h" +#include "tx_api.h" + + +void _tx_timer_interrupt(void); + + + +// -------------------------------------------------------- + +void hw_setup(void) +{ + long long current_time; + + + setGICAddr((void*)0x2C001000, (void*)0x2C002000); + + // + // Configure interrupt controller (GICv2 assumed) + // + enableGIC(); + enableCPUInterface(); + enableNonSecureCPUInterface(); + setPriorityMask(0xFF); + enableSecureFIQs(); + + // Secure Physical Timer (ID 29) + enableIntID(29); + setIntPriority(29, 0); + makeIntGroup0(29); + + // Non-Secure Physical Timer (ID 30) + enableIntID(30); + setIntPriority(30, 0); + makeIntGroup1(30); + + + // + // Configure timer + // + configSecureEL1TimerAccess(SCR_ENABLE_SECURE_EL1_ACCESS); + + current_time = getPhysicalCount(); + + // Configure the Secure Physical Timer + setSEL1PhysicalCompValue(current_time + 10000); + setSEL1PhysicalTimerCtrl(CNTPS_CTL_ENABLE); + + // Configure the Non-Secure Physical Timer + setNSEL1PhysicalCompValue(current_time + 20000); + setNSEL1PhysicalTimerCtrl(CNTP_CTL_ENABLE); + + + // NOTE: + // This code assumes that the IRQ and FIQ exceptions + // have been routed to the appropriate EL. In this + // example that is done in the startup.s file +} + + +// -------------------------------------------------------- + +void fiqHandler(void) +{ + unsigned int ID; + +// printf("Hello from the FIQ handler\n"); + + ID = readIntAck(); + setSEL1PhysicalTimerCtrl(0); // Disable timer to clear interrupt + writeEOI(ID); + + return; +} + +// -------------------------------------------------------- + +void irqHandler(void) +{ + unsigned int ID; + unsigned long long current_time; + +// printf("Hello from the IRQ handler\n"); + + ID = readAliasedIntAck(); + setNSEL1PhysicalTimerCtrl(0); // Disable timer to clear interrupt + writeAliasedEOI(ID); + + current_time = getPhysicalCount(); + setNSEL1PhysicalCompValue(current_time + 20000); + setNSEL1PhysicalTimerCtrl(CNTP_CTL_ENABLE); + + //tx_thread_resume(&thread_1); + _tx_timer_interrupt(); + + return; +} + +// -------------------------------------------------------- diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c new file mode 100644 index 00000000..db5318f0 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.c @@ -0,0 +1,381 @@ +/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight + threads of different priorities, using a message queue, semaphore, mutex, event flags group, + byte pool, and block pool. */ + +#include "tx_api.h" +#include <stddef.h> + +#define DEMO_STACK_SIZE 2048 +#define DEMO_BYTE_POOL_SIZE 64000 +#define DEMO_BLOCK_POOL_SIZE 100 +#define DEMO_QUEUE_SIZE 100 + + +/* Define the ThreadX object control blocks... */ + +TX_THREAD thread_0; +TX_THREAD thread_1; +TX_THREAD thread_2; +TX_THREAD thread_3; +TX_THREAD thread_4; +TX_THREAD thread_5; +TX_THREAD thread_6; +TX_THREAD thread_7; +TX_QUEUE queue_0; +TX_SEMAPHORE semaphore_0; +TX_MUTEX mutex_0; +TX_EVENT_FLAGS_GROUP event_flags_0; +TX_BYTE_POOL byte_pool_0; +TX_BLOCK_POOL block_pool_0; + + +/* 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; + + +UCHAR memory_pool[DEMO_BYTE_POOL_SIZE]; + +/* Define thread prototypes. */ + +void thread_0_entry(ULONG thread_input); +void thread_1_entry(ULONG thread_input); +void thread_2_entry(ULONG thread_input); +void thread_3_and_4_entry(ULONG thread_input); +void thread_5_entry(ULONG thread_input); +void thread_6_and_7_entry(ULONG thread_input); + + +/* Define board-specific hardware setup. */ + +void hw_setup(void); + + +/* Define main entry point. */ + +int main() +{ + + /* Setup hardware. */ + hw_setup(); + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +UCHAR *pointer = TX_NULL; + + + /* Create a byte memory pool from which to allocate the thread stacks. */ + tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_pool, DEMO_BYTE_POOL_SIZE); + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Allocate the stack for thread 0. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + + + /* Allocate the stack for thread 1. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 1 and 2. These threads pass information through a ThreadX + message queue. It is also interesting to note that these threads have a time + slice. */ + tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 2. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 3. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. + An interesting thing here is that both threads share the same instruction area. */ + tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 4. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 5. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create thread 5. This thread simply pends on an event flag which will be set + by thread_0. */ + tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 6. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ + tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 7. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the message queue. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); + + /* Create the message queue shared by threads 1 and 2. */ + tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); + + /* Create the semaphore used by threads 3 and 4. */ + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Create the event flags group used by threads 1 and 5. */ + tx_event_flags_create(&event_flags_0, "event flags 0"); + + /* Create the mutex used by thread 6 and 7 without priority inheritance. */ + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Allocate the memory for a small block pool. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); + + /* Create a block memory pool to allocate a message buffer from. */ + tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); + + /* Allocate a block and release the block memory. */ + tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); + + /* Release the block back to the pool. */ + tx_block_release(pointer); +} + + + +/* Define the test threads. */ + +void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sits in while-forever-sleep loop. */ + while(1) + { + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Sleep for 10 ticks. */ + tx_thread_sleep(10); + + /* Set event flag 0 to wakeup thread 5. */ + status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sends messages to a queue shared by thread 2. */ + while(1) + { + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Send message to queue 0. */ + status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER); + + /* Check completion status. */ + if (status != TX_SUCCESS) + break; + + /* Increment the message sent. */ + thread_1_messages_sent++; + } +} + + +void thread_2_entry(ULONG thread_input) +{ + +ULONG received_message; +UINT status; + + + /* This thread retrieves messages placed on the queue by thread 1. */ + while(1) + { + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Retrieve a message from the queue. */ + status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER); + + /* Check completion status and make sure the message is what we + expected. */ + if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received)) + break; + + /* Otherwise, all is okay. Increment the received message count. */ + thread_2_messages_received++; + } +} + + +void thread_3_and_4_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 3 and thread 4. As the loop + below shows, these function compete for ownership of semaphore_0. */ + while(1) + { + + /* Increment the thread counter. */ + if (thread_input == 3) + thread_3_counter++; + else + thread_4_counter++; + + /* Get the semaphore with suspension. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the semaphore. */ + tx_thread_sleep(2); + + /* Release the semaphore. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_5_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_flags; + + + /* This thread simply waits for an event in a forever loop. */ + while(1) + { + + /* Increment the thread counter. */ + thread_5_counter++; + + /* Wait for event flag 0. */ + status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_flags != 0x1)) + break; + } +} + + +void thread_6_and_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 6 and thread 7. As the loop + below shows, these function compete for ownership of mutex_0. */ + while(1) + { + + /* Increment the thread counter. */ + if (thread_input == 6) + thread_6_counter++; + else + thread_7_counter++; + + /* Get the mutex with suspension. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Get the mutex again with suspension. This shows + that an owning thread may retrieve the mutex it + owns multiple times. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the mutex. */ + tx_thread_sleep(2); + + /* Release the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Release the mutex again. This will actually + release ownership since it was obtained twice. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.txt b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.txt new file mode 100644 index 00000000..90c80d28 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/sample_threadx.txt @@ -0,0 +1,15 @@ +LOAD 0x80000000 +{ + BASE 0x80000000 + { + * (+RO) + } + + RAM +0x0 + { + * (+RW, +ZI) + } + + ARM_LIB_STACKHEAP 0x80090000 EMPTY -0x00040000 + {} +}
\ No newline at end of file diff --git a/ports/cortex_a5x/ac6/example_build/sample_threadx/startup.S b/ports/cortex_a5x/ac6/example_build/sample_threadx/startup.S new file mode 100644 index 00000000..8b1f8f3b --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/sample_threadx/startup.S @@ -0,0 +1,199 @@ +//================================================================== +// Copyright ARM Ltd 2012. All rights reserved. +// +// ARMv8 example - Startup Code +//================================================================== + + .section BOOT,"ax" + .align 3 + +// ------------------------------------------------------------ + +.equ Mode_USR, 0x10 + +.equ AArch32_Mode_USR, 0x10 +.equ AArch32_Mode_FIQ, 0x11 +.equ AArch32_Mode_IRQ, 0x12 +.equ AArch32_Mode_SVC, 0x13 +.equ AArch32_Mode_ABT, 0x17 +.equ AArch32_Mode_UNDEF, 0x1B +.equ AArch32_Mode_SYS, 0x1F +.equ AArch32_Mode_HYP, 0x1A +.equ AArch32_Mode_MON, 0x16 + +.equ AArch64_EL2_SP2, 0x09 // EL2h +.equ AArch64_EL2_SP0, 0x08 // EL2t +.equ AArch64_EL1_SP1, 0x05 // EL1h +.equ AArch64_EL1_SP0, 0x04 // EL1t +.equ AArch64_EL0_SP0, 0x00 + +.equ AArch32_State_Thumb, 0x20 +.equ AArch32_State_ARM, 0x00 + +// ------------------------------------------------------------ + +.equ TT_S1_TABLE, 0x00000000000000003 // NSTable=0, PXNTable=0, UXNTable=0, APTable=0 + +// TT block entries templates (L1 and L2, NOT L3) +// Assuming table contents: +// 0 = b01000100 = Normal, Inner/Outer Non-Cacheable +// 1 = b11111111 = Normal, Inner/Outer WB/WA/RA +// 2 = b00000000 = Device-nGnRnE +.equ TT_S1_FAULT, 0x0 +.equ TT_S1_NORMAL_NO_CACHE, 0x00000000000000401 // Index = 0, AF=1 +.equ TT_S1_NORMAL_WBWA, 0x00000000000000405 // Index = 1, AF=1 +.equ TT_S1_DEVICE_nGnRnE, 0x00000000000000409 // Index = 2, AF=1 + +.equ TT_S1_UXN, (1 << 54) +.equ TT_S1_PXN, (1 << 53) +.equ TT_S1_nG, (1 << 11) +.equ TT_S1_NS, (1 << 5) + +.equ TT_S1_NON_SHARED, (0 << 8) // Non-shareable +.equ TT_S1_INNER_SHARED, (3 << 8) // Inner-shareable +.equ TT_S1_OUTER_SHARED, (2 << 8) // Outer-shareable + +.equ TT_S1_PRIV_RW, (0x0) +.equ TT_S1_PRIV_RO, (0x2 << 6) +.equ TT_S1_USER_RW, (0x1 << 6) +.equ TT_S1_USER_RO, (0x3 << 6) + +// ------------------------------------------------------------ + + .global start64 + .type start64, @function +start64: + + // Clear registers + // --------------- + // This is primarily for RTL simulators, to avoid + // possibility of X propergation + MOV x0, #0 + MOV x1, #0 + MOV x2, #0 + MOV x3, #0 + MOV x4, #0 + MOV x5, #0 + MOV x6, #0 + MOV x7, #0 + MOV x8, #0 + MOV x9, #0 + MOV x10, #0 + MOV x11, #0 + MOV x12, #0 + MOV x13, #0 + MOV x14, #0 + MOV x15, #0 + MOV x16, #0 + MOV x17, #0 + MOV x18, #0 + MOV x19, #0 + MOV x20, #0 + MOV x21, #0 + MOV x22, #0 + MOV x23, #0 + MOV x24, #0 + MOV x25, #0 + MOV x26, #0 + MOV x27, #0 + MOV x28, #0 + MOV x29, #0 + MOV x30, #0 + + // Which core am I + // ---------------- + MRS x0, MPIDR_EL1 + AND x0, x0, #0xFF // Mask off to leave Aff0 + CBZ x0, boot // If core 0, run the primary init code +sleep: + WFI + B sleep +boot: + + + // Disable trapping of CPTR_EL3 accesses or use of Adv.SIMD/FPU + // ------------------------------------------------------------- + MOV x0, #0 // Clear all trap bits + MSR CPTR_EL3, x0 + + + // Install vector table + // --------------------- + LDR x0, vector_table_address + MSR VBAR_EL3, x0 + + + // Configure SCR_EL3 + // ------------------ + MOV w1, #0 // Initial value of register is unknown + ORR w1, w1, #(1 << 11) // Set ST bit (Secure EL1 can access CNTPS_TVAL_EL1, CNTPS_CTL_EL1 & CNTPS_CVAL_EL1) + ORR w1, w1, #(1 << 10) // Set RW bit (EL1 is AArch64, as this is the Secure world) + ORR w1, w1, #(1 << 3) // Set EA bit (SError routed to EL3) + ORR w1, w1, #(1 << 2) // Set FIQ bit (FIQs routed to EL3) + ORR w1, w1, #(1 << 1) // Set IRQ bit (IRQs routed to EL3) + MSR SCR_EL3, x1 + + + // + // Cortex-A series specified configuration + // + .ifdef CORTEXA + // Configure ACTLR_EL1 + // -------------------- + // These bits are IMP DEF, so need to different for different + // processors + //MRS x1, ACTLR_EL1 + //ORR x1, x1, #1 // Enable EL1 access to ACTLR_EL1 + //ORR x1, x1, #(1 << 1) // Enable EL1 access to CPUECTLR_EL1 + //ORR x1, x1, #(1 << 4) // Enable EL1 access to L2CTLR_EL1 + //ORR x1, x1, #(1 << 5) // Enable EL1 access to L2ECTLR_EL1 + //ORR x1, x1, #(1 << 6) // Enable EL1 access to L2ACTLR_EL1 + //MSR ACTLR_EL1, x1 + + // Configure CPUECTLR_EL1 + // ----------------------- + // These bits are IMP DEF, so need to different for different + // processors + // SMPEN - bit 6 - Enables the processor to receive cache + // and TLB maintenance operations + // + // NOTE: For Cortex-A57/53 CPUEN should be set beforebefore + // enabling the caches and MMU, or performing any cache + // and TLB maintenance operations. + //MRS x0, S3_1_c15_c2_1 // Read EL1 CPU Extended Control Register + //ORR x0, x0, #(1 << 6) // Set the SMPEN bit + //MSR S3_1_c15_c2_1, x0 // Write EL1 CPU Extended Control Register + //ISB + .endif + + + // Ensure changes to system register are visible before MMU enabled + ISB + + + // Enable Interrupts + // ------------------ + MSR DAIFClr, 0x3 + + + // Branch to scatter loading and C library init code + .global __main + B __main + +//================================================================== +// Manually created literals pool +//================================================================== + .align 3 + +lit_stackheap_limit: + .global Image$$ARM_LIB_STACKHEAP$$ZI$$Limit // Linker symbol from scatter file + .quad (Image$$ARM_LIB_STACKHEAP$$ZI$$Limit) + +vector_table_address: + .global el3_vectors + .quad el3_vectors + +// ------------------------------------------------------------ +// End of file +// ------------------------------------------------------------ + diff --git a/ports/cortex_a5x/ac6/example_build/tx/.cproject b/ports/cortex_a5x/ac6/example_build/tx/.cproject new file mode 100644 index 00000000..11f9c6c9 --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/tx/.cproject @@ -0,0 +1,129 @@ +<?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.1636501669"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.1636501669" moduleId="org.eclipse.cdt.core.settings" name="Debug"> + <externalSettings> + <externalSetting> + <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/tx"/> + <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/tx/Debug"/> + <entry flags="RESOLVED" kind="libraryFile" name="tx" srcPrefixMapping="" srcRootPath=""/> + </externalSetting> + </externalSettings> + <extensions> + <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.1636501669" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug"> + <folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.1636501669." name="/" resourcePath=""> + <toolChain id="com.arm.toolchain.v6.lib.debug.372997136" name="ARM Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.lib.debug"> + <targetPlatform id="com.arm.eclipse.build.config.v6.lib.debug.1636501669..1913630610" name=""/> + <builder buildPath="${workspace_loc:/tx}/Debug" id="com.arm.toolchain.v6.builder.1983518587" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.arm.toolchain.v6.builder"/> + <tool id="com.arm.tool.c.compiler.v6.424515954" name="ARM C Compiler 6" superClass="com.arm.tool.c.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.min" id="com.arm.tool.c.compiler.v6.base.option.optlevel.1943677123" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.tool.c.compiler.v6.base.options.debug.level.1549650007" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" valueType="enumerated"/> + <option id="com.arm.tool.c.compiler.v6.base.option.target.1356370649" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="aarch64-arm-none-eabi" valueType="string"/> + <option id="com.arm.tool.c.compiler.v6.base.option.cpu.1958530753" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-a53+fp" valueType="string"/> + <option id="com.arm.tool.c.compiler.v6.base.option.defmac.27547789" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols"> + <listOptionValue builtIn="false" value="STANDALONE"/> + <listOptionValue builtIn="false" value="ENABLE_ARM_FP"/> + </option> + <option id="com.arm.tool.c.compiler.v6.base.options.preproc.enableToolSpecificSettings.564945141" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.preproc.enableToolSpecificSettings" useByScannerDiscovery="false" value="true" valueType="boolean"/> + <option id="com.arm.tool.c.compiler.v6.base.option.incpath.1612505103" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath"> + <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_generic}""/> + <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/> + </option> + <inputType id="com.arm.tool.c.compiler.v6.base.input.1675127320" superClass="com.arm.tool.c.compiler.v6.base.input"/> + <inputType id="com.arm.tool.cpp.compiler.v6.base.input.1720461009" superClass="com.arm.tool.cpp.compiler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.cpp.compiler.v6.1361684972" name="ARM C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.min" id="com.arm.tool.c.compiler.v6.base.option.optlevel.612579770" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.tool.c.compiler.v6.base.options.debug.level.1772335065" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/> + </tool> + <tool id="com.arm.tool.assembler.v6.1230485781" name="ARM Assembler 6" superClass="com.arm.tool.assembler.v6"> + <option defaultValue="com.arm.tool.assembler.v6.base.options.debug.level.std" id="com.arm.tool.assembler.v6.base.options.debug.level.2059874867" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/> + <option id="com.arm.tool.assembler.v6.base.option.target.1596122891" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" value="aarch64-arm-none-eabi" valueType="string"/> + <option id="com.arm.tool.assembler.v6.base.option.cpu.654928087" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" value="cortex-a53+fp" valueType="string"/> + <option id="com.arm.tool.assembler.v6.base.option.defmac.162845590" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac"/> + <option id="com.arm.tool.assembler.v6.base.options.preproc.enableToolSpecificSettings.1821750188" name="Enable tool specific settings" superClass="com.arm.tool.assembler.v6.base.options.preproc.enableToolSpecificSettings" useByScannerDiscovery="false" value="true" valueType="boolean"/> + <option id="com.arm.tool.assembler.v6.base.option.incpath.920333443" name="Include path (-I)" superClass="com.arm.tool.assembler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath"/> + <inputType id="com.arm.tool.assembler.v6.base.input.157969473" superClass="com.arm.tool.assembler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.c.linker.v6.1251436674" name="ARM Linker 6" superClass="com.arm.tool.c.linker.v6"/> + <tool id="com.arm.tool.librarian.v6.1167637188" name="ARM Librarian 6" superClass="com.arm.tool.librarian.v6"/> + </toolChain> + </folderInfo> + <sourceEntries> + <entry excluding="src_generic/tx_misra.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + </sourceEntries> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + <cconfiguration id="com.arm.eclipse.build.config.v6.lib.release.1521587399"> + <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.release.1521587399" moduleId="org.eclipse.cdt.core.settings" name="Release"> + <externalSettings> + <externalSetting> + <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/tx"/> + <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/tx/Release"/> + <entry flags="RESOLVED" kind="libraryFile" name="tx" srcPrefixMapping="" srcRootPath=""/> + </externalSetting> + </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.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.release.1521587399" name="Release" parent="com.arm.eclipse.build.config.v6.lib.release"> + <folderInfo id="com.arm.eclipse.build.config.v6.lib.release.1521587399." name="/" resourcePath=""> + <toolChain id="com.arm.toolchain.v6.lib.release.2074068559" name="ARM Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.lib.release"> + <targetPlatform id="com.arm.eclipse.build.config.v6.lib.release.1521587399..1369138044" name=""/> + <builder buildPath="${workspace_loc:/tx}/Release" id="com.arm.toolchain.v6.builder.356216328" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/> + <tool id="com.arm.tool.c.compiler.v6.910156028" name="ARM C Compiler 6" superClass="com.arm.tool.c.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.high" id="com.arm.tool.c.compiler.v6.base.option.optlevel.49171447" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" useByScannerDiscovery="true" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.tool.c.compiler.v6.base.options.debug.level.203884217" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" valueType="enumerated"/> + <inputType id="com.arm.tool.c.compiler.v6.base.input.949469320" superClass="com.arm.tool.c.compiler.v6.base.input"/> + <inputType id="com.arm.tool.cpp.compiler.v6.base.input.866107816" superClass="com.arm.tool.cpp.compiler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.cpp.compiler.v6.2136467342" name="ARM C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6"> + <option defaultValue="com.arm.tool.c.compiler.v6.base.option.optlevel.high" id="com.arm.tool.c.compiler.v6.base.option.optlevel.62249493" name="Optimization level" superClass="com.arm.tool.c.compiler.v6.base.option.optlevel" valueType="enumerated"/> + <option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.tool.c.compiler.v6.base.options.debug.level.93807078" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/> + </tool> + <tool id="com.arm.tool.assembler.v6.1185271435" name="ARM Assembler 6" superClass="com.arm.tool.assembler.v6"> + <option defaultValue="com.arm.tool.assembler.v6.base.options.debug.level.none" id="com.arm.tool.assembler.v6.base.options.debug.level.2069699697" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/> + <inputType id="com.arm.tool.assembler.v6.base.input.1112095021" superClass="com.arm.tool.assembler.v6.base.input"/> + </tool> + <tool id="com.arm.tool.c.linker.v6.1769504167" name="ARM Linker 6" superClass="com.arm.tool.c.linker.v6"/> + <tool id="com.arm.tool.librarian.v6.801428272" name="ARM Librarian 6" superClass="com.arm.tool.librarian.v6"/> + </toolChain> + </folderInfo> + <sourceEntries> + <entry excluding="src_generic/tx_misra.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> + </sourceEntries> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> + </cconfiguration> + </storageModule> + <storageModule moduleId="cdtBuildSystem" version="4.0.0"> + <project id="tx.com.arm.eclipse.build.project.v6.lib.1209080418" name="Static Library" projectType="com.arm.eclipse.build.project.v6.lib"/> + </storageModule> + <storageModule moduleId="scannerConfiguration"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> + <storageModule moduleId="refreshScope" versionNumber="2"> + <configuration configurationName="Debug"> + <resource resourceType="PROJECT" workspacePath="/tx"/> + </configuration> + <configuration configurationName="Release"> + <resource resourceType="PROJECT" workspacePath="/tx"/> + </configuration> + </storageModule> + <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> +</cproject> diff --git a/ports/cortex_a5x/ac6/example_build/tx/.project b/ports/cortex_a5x/ac6/example_build/tx/.project new file mode 100644 index 00000000..863ca5cb --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/tx/.project @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>tx</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> + <triggers>clean,full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.cdt.core.cnature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> + <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> + </natures> + <linkedResources> + <link> + <name>inc_generic</name> + <type>2</type> + <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI> + </link> + <link> + <name>inc_port</name> + <type>2</type> + <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI> + </link> + <link> + <name>src_generic</name> + <type>2</type> + <locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/src</locationURI> + </link> + <link> + <name>src_port</name> + <type>2</type> + <locationURI>$%7BPARENT-2-PROJECT_LOC%7D/src</locationURI> + </link> + </linkedResources> +</projectDescription> diff --git a/ports/cortex_a5x/ac6/example_build/tx/.settings/language.settings.xml b/ports/cortex_a5x/ac6/example_build/tx/.settings/language.settings.xml new file mode 100644 index 00000000..118220fc --- /dev/null +++ b/ports/cortex_a5x/ac6/example_build/tx/.settings/language.settings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<project> + <configuration id="com.arm.eclipse.build.config.v6.lib.debug.1636501669" name="Debug"> + <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> + <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> + <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> + <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> + <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-294697026837367808" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="ARM Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <language-scope id="org.eclipse.cdt.core.gcc"/> + <language-scope id="org.eclipse.cdt.core.g++"/> + </provider> + </extension> + </configuration> + <configuration id="com.arm.eclipse.build.config.v6.lib.release.1521587399" name="Release"> + <extension point="org.eclipse.cdt.core.LanguageSettingsProvider"> + <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> + <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> + <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/> + <provider class="com.arm.eclipse.builder.armcc.discovery.ArmCompiler6LanguageSettingsProvider" console="false" env-hash="-264130677454984672" id="com.arm.eclipse.builder.armcc.v6.langprovider" keep-relative-paths="false" name="ARM Compiler 6 Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true"> + <language-scope id="org.eclipse.cdt.core.gcc"/> + <language-scope id="org.eclipse.cdt.core.g++"/> + </provider> + </extension> + </configuration> +</project> diff --git a/ports/cortex_a5x/ac6/inc/tx_port.h b/ports/cortex_a5x/ac6/inc/tx_port.h new file mode 100644 index 00000000..33a029ff --- /dev/null +++ b/ports/cortex_a5x/ac6/inc/tx_port.h @@ -0,0 +1,367 @@ +/**************************************************************************/ +/* */ +/* 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 Cortex-A5x/ARM */ +/* 6.0.1 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + + +/* Determine if the optional ThreadX user define file should be used. */ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif + + +/* Define compiler library include files. */ + +#include <stdlib.h> +#include <string.h> + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef int LONG; +typedef unsigned int ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Override the alignment type to use 64-bit alignment and storage for pointers. */ + +#define ALIGN_TYPE_DEFINED +typedef unsigned long long ALIGN_TYPE; + + +/* Override the free block marker for byte pools to be a 64-bit constant. */ + +#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE) + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 4096 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + + +/* Define various constants for the ThreadX ARM port. */ + +#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */ +#define TX_INT_ENABLE 0x00 /* Enable IRQ & FIQ interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#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. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_fp_enable; +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + + +/* Define the ThreadX object creation extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Determine if the ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#ifndef TX_DISABLE_INLINE + +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) b = (UINT) __builtin_ctz((unsigned int) m); + +#endif + + +/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout + can figure out what thread timeout to process. */ + +#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_thread_timeout_ptr; + + +/* Define the thread timeout setup logic in _tx_thread_create. */ + +#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \ + (t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \ + (t) -> tx_thread_timer.tx_timer_internal_thread_timeout_ptr = (VOID *) (t); + + +/* Define the thread timeout pointer setup in _tx_thread_timeout. */ + +#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_thread_timeout_ptr; + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +#ifndef TX_DISABLE_INLINE + +/* Define macros, with in-line assembly for performance. */ + +__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void) +{ + +unsigned long long daif_value; + + __asm__ volatile (" MRS %0, DAIF ": "=r" (daif_value) ); + __asm__ volatile (" MSR DAIFSet, 0x3" : : : "memory" ); + return((unsigned int) daif_value); +} + +__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int daif_value) +{ + +unsigned long long temp; + + temp = (unsigned long long) daif_value; + __asm__ volatile (" MSR DAIF,%0": : "r" (temp): "memory" ); +} + + +#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save; +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupts(interrupt_save); + +#else + +unsigned int _tx_thread_interrupt_disable(void); +unsigned int _tx_thread_interrupt_restore(UINT old_posture); + + +#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); +#endif + + +/* Define FP extension for the Cortex-A5x. Each is assumed to be called in the context of the executing + thread. */ + +#ifndef TX_SOURCE_CODE +#define tx_thread_fp_enable _tx_thread_fp_enable +#define tx_thread_fp_disable _tx_thread_fp_disable +#endif + +VOID tx_thread_fp_enable(VOID); +VOID tx_thread_fp_disable(VOID); + + +/* Define the interrupt lockout macros for each ThreadX object. */ + +#define TX_BLOCK_POOL_DISABLE TX_DISABLE +#define TX_BYTE_POOL_DISABLE TX_DISABLE +#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE +#define TX_MUTEX_DISABLE TX_DISABLE +#define TX_QUEUE_DISABLE TX_DISABLE +#define TX_SEMAPHORE_DISABLE TX_DISABLE + + +/* Define the version ID of ThreadX. This may be utilized by the application. */ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-A5x/ARM Version 6.0 *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +#endif + + + + diff --git a/ports/cortex_a5x/ac6/readme_threadx.txt b/ports/cortex_a5x/ac6/readme_threadx.txt new file mode 100644 index 00000000..6907bd0f --- /dev/null +++ b/ports/cortex_a5x/ac6/readme_threadx.txt @@ -0,0 +1,255 @@ + Microsoft's Azure RTOS ThreadX for Cortex-A5x + + Using the ARM Compiler 6 & DS + +1. Open the Azure RTOS Workspace + +In order to build the ThreadX library and the ThreadX demonstration first load +the Azure RTOS Workspace, which is located inside your ThreadX installation +directory. + +Note: the workspace and projects were made using DS-5, so DS will prompt you +to migrate the projects. This is expected, so please do so. + +2. Building the ThreadX run-time Library + +Building the ThreadX library is easy; simply select the Eclipse project file +"tx" and then select the build button. You should now observe the compilation +and assembly of the ThreadX library. This project build produces the ThreadX +library file tx.a. + + +3. Demonstration System + +The ThreadX demonstration is designed to execute under the DS debugger on the +VE-AEMv8x1 Bare Metal simulator. + +Building the demonstration is easy; simply open the workspace file, select the +sample_threadx project, and select the build button. Next, right-click on the +project and select "Debug As -> Debug Configurations". The debugger is setup +for VE_AEMv8x1 Bare Metal Debug, so selecting "Debug" will launch the simulator, +load the sample_threadx.axf ELF file and run to main. You are now ready to +execute the ThreadX demonstration. + + +4. System Initialization + +The entry point in ThreadX for the Cortex-A5x using ARM tools is at label +start64. This is defined within the ARM compiler's startup code. In addition, +this is where all static and global pre-set C variable initialization processing +takes place. + +The ThreadX tx_initialize_low_level.s file is responsible for determining the +first available RAM address for use by the application, which is supplied as the +sole input parameter to your application definition function, tx_application_define. + + +5. Register Usage and Stack Frames + +The 64-bit ARM compiler assumes that registers x0-x18 are scratch registers +for each function. All other registers used by a C function must be preserved +by the function. ThreadX takes advantage of this in situations where a context +switch happens as a result of making a ThreadX service call (which is itself a +C function). In such cases, the saved context of a thread is only the +non-scratch registers. + +The following defines the saved context stack frames for context switches +that occur as a result of interrupt handling or from thread-level API calls. +All suspended threads have one of these two types of stack frames. The top +of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the +associated thread control block TX_THREAD. + + +FP not enabled and TX_THREAD.tx_thread_fp_enable == 0: + + Offset Interrupted Stack Frame Non-Interrupt Stack Frame + + 0x000 SPSR DAIF + 0x008 ELR 0 + 0x010 x28 x27 + 0x018 reserved x28 + 0x020 x26 x25 + 0x028 x27 x26 + 0x030 x24 x23 + 0x038 x25 x24 + 0x040 x22 x21 + 0x048 x23 x22 + 0x050 x20 x19 + 0x058 x21 x20 + 0x060 x18 x29 + 0x068 x19 x30 + 0x070 x16 + 0x078 x17 + 0x080 x14 + 0x088 x15 + 0x090 x12 + 0x098 x13 + 0x0A0 x10 + 0x0A8 x11 + 0x0B0 x8 + 0x0B8 x9 + 0x0C0 x6 + 0x0C8 x7 + 0x0D0 x4 + 0x0D8 x5 + 0x0E0 x2 + 0x0E8 x3 + 0x0F0 x0 + 0x0F8 x1 + 0x100 x29 + 0x108 x30 + + +FP enabled and TX_THREAD.tx_thread_fp_enable == 1: + + Offset Interrupted Stack Frame Non-Interrupt Stack Frame + + 0x000 SPSR DAIF + 0x008 ELR 0 + 0x010 FPSR FPSR + 0x018 FPCR FPCR + 0x020 q30 q14 + 0x030 q31 q15 + 0x040 q28 q12 + 0x050 q29 q13 + 0x060 q26 q10 + 0x070 q27 q11 + 0x080 q24 q8 + 0x090 q25 q9 + 0x0A0 q22 x27 + 0x0A8 x28 + 0x0B0 q23 x25 + 0x0B8 x26 + 0x0C0 q20 x23 + 0x0C8 x24 + 0x0D0 q21 x21 + 0x0D8 x22 + 0x0E0 q18 x19 + 0x0E8 x20 + 0x0F0 q19 x29 + 0x0F8 x30 + 0x100 q16 + 0x110 q17 + 0x120 q14 + 0x130 q15 + 0x140 q12 + 0x150 q13 + 0x160 q10 + 0x170 q11 + 0x180 q8 + 0x190 q9 + 0x1A0 q6 + 0x1B0 q7 + 0x1C0 q4 + 0x1D0 q5 + 0x1E0 q2 + 0x1F0 q3 + 0x200 q0 + 0x210 q1 + 0x220 x28 + 0x228 reserved + 0x230 x26 + 0x238 x27 + 0x240 x24 + 0x248 x25 + 0x250 x22 + 0x258 x23 + 0x260 x20 + 0x268 x21 + 0x270 x18 + 0x278 x19 + 0x280 x16 + 0x288 x17 + 0x290 x14 + 0x298 x15 + 0x2A0 x12 + 0x2A8 x13 + 0x2B0 x10 + 0x2B8 x11 + 0x2C0 x8 + 0x2C8 x9 + 0x2D0 x6 + 0x2D8 x7 + 0x2E0 x4 + 0x2E8 x5 + 0x2F0 x2 + 0x2F8 x3 + 0x300 x0 + 0x308 x1 + 0x310 x29 + 0x318 x30 + + + +6. Improving Performance + +The distribution version of ThreadX is built without any compiler optimizations. +This makes it easy to debug because you can trace or set breakpoints inside of +ThreadX itself. Of course, this costs some performance. To make it run faster, +you can change the project settings to the desired compiler optimization level. + +In addition, you can eliminate the ThreadX basic API error checking by +compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING +defined. + + +7. Interrupt Handling + +ThreadX provides complete and high-performance interrupt handling for Cortex-A5x +targets. Interrupts handlers for the 64-bit mode of the Cortex-A5x have the following +format: + + .global irq_handler +irq_handler: + + STP x29, x30, [sp, #-16]! + BL _tx_thread_context_save + + /* Your ISR call goes here! */ + BL application_isr_handler + + B _tx_thread_context_restore + +By default, ThreadX assumes EL3 level of execution. Running and taking exceptions in EL1 +and EL2 can be done by simply building the ThreadX library with either EL1 or EL2 defined. + + +8. ThreadX Timer Interrupt + +ThreadX requires a periodic interrupt source to manage all time-slicing, thread sleeps, +timeouts, and application timers. Without such a timer interrupt source, these services +are not functional. However, all other ThreadX services are operational without a +periodic timer source. + + +9. ARM FP Support + +By default, FP support is disabled for each thread. If saving the context of the FP registers +is needed, the following API call must be made from the context of the application thread - before +the FP usage: + +void tx_thread_fp_enable(void); + +After this API is called in the application, FP registers will be saved/restored for this thread if it +is preempted via an interrupt. All other suspension of the this thread will not require the FP registers +to be saved/restored. + +To disable FP register context saving, simply call the following API: + +void tx_thread_fp_disable(void); + + +10. Revision History + +For generic code revision information, please refer to the readme_threadx_generic.txt +file, which is included in your distribution. The following details the revision +information associated with this specific port of ThreadX: + +06/30/2020 Initial ThreadX 6.0.1 version for Cortex-A5x using ARM tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/ports/cortex_a5x/ac6/src/tx_initialize_low_level.S b/ports/cortex_a5x/ac6/src/tx_initialize_low_level.S new file mode 100644 index 00000000..699a819a --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_initialize_low_level.S @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for any low-level processor */ +/* initialization, including setting up interrupt vectors, setting */ +/* up a periodic timer interrupt source, saving the system stack */ +/* pointer for use in ISR processing later, and finding the first */ +/* available RAM memory address for tx_application_define. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_initialize_low_level(VOID) +{ */ + .global _tx_initialize_low_level + .type _tx_initialize_low_level, @function +_tx_initialize_low_level: + + MSR DAIFSet, 0x3 // Lockout interrupts + + + /* Save the system stack pointer. */ + /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */ + + LDR x0, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr + MOV x1, sp // Pickup SP + BIC x1, x1, #0xF // Get 16-bit alignment + STR x1, [x0] // Store system stack + + /* Save the first available memory address. */ + /* _tx_initialize_unused_memory = (VOID_PTR) Image$$ZI$$Limit; */ + + LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr + LDR x1, =zi_limit // Pickup unused memory address + LDR x1, [x1] // + STR x1, [x0] // Store unused memory address + + /* Done, return to caller. */ + + RET // Return to caller +/* } */ + + +zi_limit: + .quad (Image$$ARM_LIB_STACKHEAP$$ZI$$Limit) + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_context_restore.S b/ports/cortex_a5x/ac6/src/tx_thread_context_restore.S new file mode 100644 index 00000000..b8de07ac --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_context_restore.S @@ -0,0 +1,302 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +*/ + +/* .set ENABLE_ARM_FP,1 */ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores the interrupt context if it is processing a */ +/* nested interrupt. If not, it returns to the interrupt thread if no */ +/* preemption is necessary. Otherwise, if preemption is necessary or */ +/* if no thread was running, the function returns to the scheduler. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling routine */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_context_restore(VOID) +{ */ + .global _tx_thread_context_restore + .type _tx_thread_context_restore, @function +_tx_thread_context_restore: + + /* Lockout interrupts. */ + + MSR DAIFSet, 0x3 // Lockout interrupts + +.ifdef 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 + + /* Determine if interrupts are nested. */ + /* if (--_tx_thread_system_state) + { */ + + LDR x3, =_tx_thread_system_state // Pickup address of system state var + LDR w2, [x3, #0] // Pickup system state + SUB w2, w2, #1 // Decrement the counter + STR w2, [x3, #0] // Store the counter + CMP w2, #0 // Was this the first interrupt? + BEQ __tx_thread_not_nested_restore // If so, not a nested restore + + /* Interrupts are nested. */ + + /* Just recover the saved registers and return to the point of + interrupt. */ + + LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL +.ifdef EL1 + MSR SPSR_EL1, x4 // Setup SPSR for return + MSR ELR_EL1, x5 // Setup point of interrupt +.else +.ifdef EL2 + MSR SPSR_EL2, x4 // Setup SPSR for return + MSR ELR_EL2, x5 // Setup point of interrupt +.else + MSR SPSR_EL3, x4 // Setup SPSR for return + MSR ELR_EL3, x5 // Setup point of interrupt +.endif +.endif + LDP x18, x19, [sp], #16 // Recover x18, x19 + LDP x16, x17, [sp], #16 // Recover x16, x17 + LDP x14, x15, [sp], #16 // Recover x14, x15 + LDP x12, x13, [sp], #16 // Recover x12, x13 + LDP x10, x11, [sp], #16 // Recover x10, x11 + LDP x8, x9, [sp], #16 // Recover x8, x9 + LDP x6, x7, [sp], #16 // Recover x6, x7 + LDP x4, x5, [sp], #16 // Recover x4, x5 + LDP x2, x3, [sp], #16 // Recover x2, x3 + LDP x0, x1, [sp], #16 // Recover x0, x1 + LDP x29, x30, [sp], #16 // Recover x29, x30 + ERET // Return to point of interrupt + + /* } */ +__tx_thread_not_nested_restore: + + /* Determine if a thread was interrupted and no preemption is required. */ + /* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr) + || (_tx_thread_preempt_disable)) + { */ + + LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr + LDR x0, [x1, #0] // Pickup actual current thread pointer + CMP x0, #0 // Is it NULL? + BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted + + LDR x3, =_tx_thread_preempt_disable // Pickup preempt disable address + LDR w2, [x3, #0] // Pickup actual preempt disable flag + CMP w2, #0 // Is it set? + BNE __tx_thread_no_preempt_restore // Yes, don't preempt this thread + LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr + LDR x2, [x3, #0] // Pickup actual execute thread pointer + CMP x0, x2 // Is the same thread highest priority? + BNE __tx_thread_preempt_restore // No, preemption needs to happen + + +__tx_thread_no_preempt_restore: + + /* Restore interrupted thread or ISR. */ + + /* Pickup the saved stack pointer. */ + /* sp = _tx_thread_current_ptr -> tx_thread_stack_ptr; */ + + LDR x4, [x0, #8] // Switch to thread stack pointer + MOV sp, x4 // + + /* Recover the saved context and return to the point of interrupt. */ + + LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1 +.ifdef EL1 + MSR SPSR_EL1, x4 // Setup SPSR for return + MSR ELR_EL1, x5 // Setup point of interrupt +.else +.ifdef EL2 + MSR SPSR_EL2, x4 // Setup SPSR for return + MSR ELR_EL2, x5 // Setup point of interrupt +.else + MSR SPSR_EL3, x4 // Setup SPSR for return + MSR ELR_EL3, x5 // Setup point of interrupt +.endif +.endif + LDP x18, x19, [sp], #16 // Recover x18, x19 + LDP x16, x17, [sp], #16 // Recover x16, x17 + LDP x14, x15, [sp], #16 // Recover x14, x15 + LDP x12, x13, [sp], #16 // Recover x12, x13 + LDP x10, x11, [sp], #16 // Recover x10, x11 + LDP x8, x9, [sp], #16 // Recover x8, x9 + LDP x6, x7, [sp], #16 // Recover x6, x7 + LDP x4, x5, [sp], #16 // Recover x4, x5 + LDP x2, x3, [sp], #16 // Recover x2, x3 + LDP x0, x1, [sp], #16 // Recover x0, x1 + LDP x29, x30, [sp], #16 // Recover x29, x30 + ERET // Return to point of interrupt + + /* } + else + { */ +__tx_thread_preempt_restore: + + LDR x4, [x0, #8] // Switch to thread stack pointer + MOV sp, x4 // + + LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1 + STP x20, x21, [sp, #-16]! // Save x20, x21 + STP x22, x23, [sp, #-16]! // Save x22, x23 + STP x24, x25, [sp, #-16]! // Save x24, x25 + STP x26, x27, [sp, #-16]! // Save x26, x27 + STP x28, x29, [sp, #-16]! // Save x28, x29 +.ifdef ENABLE_ARM_FP + LDR w3, [x0, #248] // Pickup FP enable flag + CMP w3, #0 // Is FP enabled? + BEQ _skip_fp_save // No, skip FP save + STP q0, q1, [sp, #-32]! // Save q0, q1 + STP q2, q3, [sp, #-32]! // Save q2, q3 + STP q4, q5, [sp, #-32]! // Save q4, q5 + STP q6, q7, [sp, #-32]! // Save q6, q7 + STP q8, q9, [sp, #-32]! // Save q8, q9 + STP q10, q11, [sp, #-32]! // Save q10, q11 + STP q12, q13, [sp, #-32]! // Save q12, q13 + STP q14, q15, [sp, #-32]! // Save q14, q15 + STP q16, q17, [sp, #-32]! // Save q16, q17 + STP q18, q19, [sp, #-32]! // Save q18, q19 + STP q20, q21, [sp, #-32]! // Save q20, q21 + STP q22, q23, [sp, #-32]! // Save q22, q23 + STP q24, q25, [sp, #-32]! // Save q24, q25 + STP q26, q27, [sp, #-32]! // Save q26, q27 + STP q28, q29, [sp, #-32]! // Save q28, q29 + STP q30, q31, [sp, #-32]! // Save q30, q31 + MRS x2, FPSR // Pickup FPSR + MRS x3, FPCR // Pickup FPCR + STP x2, x3, [sp, #-16]! // Save FPSR, FPCR +_skip_fp_save: +.endif + STP x4, x5, [sp, #-16]! // Save x4 (SPSR_EL3), x5 (ELR_E3) + + MOV x3, sp // Move sp into x3 + STR x3, [x0, #8] // Save stack pointer in thread control + // block + LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack + LDR x4, [x3, #0] // Pickup system stack pointer + MOV sp, x4 // Setup system stack pointer + + + /* Save the remaining time-slice and disable it. */ + /* if (_tx_timer_time_slice) + { */ + + LDR x3, =_tx_timer_time_slice // Pickup time-slice variable address + LDR w2, [x3, #0] // Pickup time-slice + CMP w2, #0 // Is it active? + BEQ __tx_thread_dont_save_ts // No, don't save it + + /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; + _tx_timer_time_slice = 0; */ + + STR w2, [x0, #36] // Save thread's time-slice + MOV w2, #0 // Clear value + STR w2, [x3, #0] // Disable global time-slice flag + + /* } */ +__tx_thread_dont_save_ts: + + + /* Clear the current task pointer. */ + /* _tx_thread_current_ptr = TX_NULL; */ + + MOV x0, #0 // NULL value + STR x0, [x1, #0] // Clear current thread pointer + + /* Return to the scheduler. */ + /* _tx_thread_schedule(); */ + + /* } */ + +__tx_thread_idle_system_restore: + + /* Just return back to the scheduler! */ + + LDR x1, =_tx_thread_schedule // Build address for _tx_thread_schedule +.ifdef EL1 + MSR ELR_EL1, x1 // Setup point of interrupt + MOV x1, #0x5 // Setup EL1 return + MSR spsr_el1, x1 // Move into SPSR +.else +.ifdef EL2 + MSR ELR_EL2, x1 // Setup point of interrupt + MOV x1, #0x9 // Setup EL2 return + MSR spsr_el2, x1 // Move into SPSR +.else + MSR ELR_EL3, x1 // Setup point of interrupt + MOV x1, #0xD // Setup EL3 return + MSR spsr_el3, x1 // Move into SPSR +.endif +.endif + ERET // Return to scheduler +/* } */ + + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_context_save.S b/ports/cortex_a5x/ac6/src/tx_thread_context_save.S new file mode 100644 index 00000000..88774af3 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_context_save.S @@ -0,0 +1,228 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves the context of an executing thread in the */ +/* beginning of interrupt processing. The function also ensures that */ +/* the system stack is used upon return to the calling ISR. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_context_save(VOID) +{ */ + .global _tx_thread_context_save + .type _tx_thread_context_save, @function +_tx_thread_context_save: + + /* Upon entry to this routine, it is assumed that IRQ/FIQ interrupts are locked + out, x29 (frame pointer), x30 (link register) are saved, we are in EL1, + and all other registers are intact. */ + + /* Check for a nested interrupt condition. */ + /* if (_tx_thread_system_state++) + { */ + + STP x0, x1, [sp, #-16]! // Save x0, x1 + STP x2, x3, [sp, #-16]! // Save x2, x3 + LDR x3, =_tx_thread_system_state // Pickup address of system state var + LDR w2, [x3, #0] // Pickup system state + CMP w2, #0 // Is this the first interrupt? + BEQ __tx_thread_not_nested_save // Yes, not a nested context save + + /* Nested interrupt condition. */ + + ADD w2, w2, #1 // Increment the nested interrupt counter + STR w2, [x3, #0] // Store it back in the variable + + /* Save the rest of the scratch registers on the stack and return to the + calling ISR. */ + + STP x4, x5, [sp, #-16]! // Save x4, x5 + STP x6, x7, [sp, #-16]! // Save x6, x7 + STP x8, x9, [sp, #-16]! // Save x8, x9 + STP x10, x11, [sp, #-16]! // Save x10, x11 + STP x12, x13, [sp, #-16]! // Save x12, x13 + STP x14, x15, [sp, #-16]! // Save x14, x15 + STP x16, x17, [sp, #-16]! // Save x16, x17 + STP x18, x19, [sp, #-16]! // Save x18, x19 +.ifdef EL1 + MRS x0, SPSR_EL1 // Pickup SPSR + MRS x1, ELR_EL1 // Pickup ELR (point of interrupt) +.else +.ifdef EL2 + MRS x0, SPSR_EL2 // Pickup SPSR + MRS x1, ELR_EL2 // Pickup ELR (point of interrupt) +.else + MRS x0, SPSR_EL3 // Pickup SPSR + MRS x1, ELR_EL3 // Pickup ELR (point of interrupt) +.endif +.endif + STP x0, x1, [sp, #-16]! // Save SPSR, ELR + +.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + /* Call the ISR enter function to indicate an ISR is executing. */ + + STP x29, x30, [sp, #-16]! // Save x29, x30 + BL _tx_execution_isr_enter // Call the ISR enter function + LDP x29, x30, [sp], #16 // Recover x29, x30 +.endif + + /* Return to the ISR. */ + + RET // Return to ISR + +__tx_thread_not_nested_save: + /* } */ + + /* Otherwise, not nested, check to see if a thread was running. */ + /* else if (_tx_thread_current_ptr) + { */ + + ADD w2, w2, #1 // Increment the interrupt counter + STR w2, [x3, #0] // Store it back in the variable + LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr + LDR x0, [x1, #0] // Pickup current thread pointer + CMP x0, #0 // Is it NULL? + BEQ __tx_thread_idle_system_save // If so, interrupt occurred in + // scheduling loop - nothing needs saving! + + /* Save minimal context of interrupted thread. */ + + STP x4, x5, [sp, #-16]! // Save x4, x5 + STP x6, x7, [sp, #-16]! // Save x6, x7 + STP x8, x9, [sp, #-16]! // Save x8, x9 + STP x10, x11, [sp, #-16]! // Save x10, x11 + STP x12, x13, [sp, #-16]! // Save x12, x13 + STP x14, x15, [sp, #-16]! // Save x14, x15 + STP x16, x17, [sp, #-16]! // Save x16, x17 + STP x18, x19, [sp, #-16]! // Save x18, x19 +.ifdef EL1 + MRS x4, SPSR_EL1 // Pickup SPSR + MRS x5, ELR_EL1 // Pickup ELR (point of interrupt) +.else +.ifdef EL2 + MRS x4, SPSR_EL2 // Pickup SPSR + MRS x5, ELR_EL2 // Pickup ELR (point of interrupt) +.else + MRS x4, SPSR_EL3 // Pickup SPSR + MRS x5, ELR_EL3 // Pickup ELR (point of interrupt) +.endif +.endif + STP x4, x5, [sp, #-16]! // Save SPSR, ELR + + /* Save the current stack pointer in the thread's control block. */ + /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ + + MOV x4, sp // + STR x4, [x0, #8] // Save thread stack pointer + + /* Switch to the system stack. */ + /* sp = _tx_thread_system_stack_ptr; */ + + LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack + LDR x4, [x3, #0] // Pickup system stack pointer + MOV sp, x4 // Setup system stack pointer + +.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + /* Call the ISR enter function to indicate an ISR is executing. */ + + STP x29, x30, [sp, #-16]! // Save x29, x30 + BL _tx_execution_isr_enter // Call the ISR enter function + LDP x29, x30, [sp], #16 // Recover x29, x30 +.endif + + RET // Return to caller + + /* } + else + { */ + +__tx_thread_idle_system_save: + + /* Interrupt occurred in the scheduling loop. */ + + /* Not much to do here, just adjust the stack pointer, and return to IRQ + processing. */ + +.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + /* Call the ISR enter function to indicate an ISR is executing. */ + + STP x29, x30, [sp, #-16]! // Save x29, x30 + BL _tx_execution_isr_enter // Call the ISR enter function + LDP x29, x30, [sp], #16 // Recover x29, x30 +.endif + + ADD sp, sp, #48 // Recover saved registers + RET // Continue IRQ processing + + /* } +} */ + + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_fp_disable.c b/ports/cortex_a5x/ac6/src/tx_thread_fp_disable.c new file mode 100644 index 00000000..8a921e86 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_fp_disable.c @@ -0,0 +1,95 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_fp_disable Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function disables the FP for the currently executing thread. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_fp_disable(VOID) +{ + +TX_THREAD *thread_ptr; +ULONG system_state; + + + /* Pickup the current thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr); + + /* Get the system state. */ + system_state = TX_THREAD_GET_SYSTEM_STATE(); + + /* Make sure it is not NULL. */ + if (thread_ptr != TX_NULL) + { + + /* Thread is running... make sure the call is from the thread context. */ + if (system_state == 0) + { + + /* Yes, now set the FP enable flag to false in the TX_THREAD structure. */ + thread_ptr -> tx_thread_fp_enable = TX_FALSE; + } + } +} + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_fp_enable.c b/ports/cortex_a5x/ac6/src/tx_thread_fp_enable.c new file mode 100644 index 00000000..818b3e8a --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_fp_enable.c @@ -0,0 +1,95 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_fp_enable Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enabled the FP for the currently executing thread. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +VOID _tx_thread_fp_enable(VOID) +{ + +TX_THREAD *thread_ptr; +ULONG system_state; + + + /* Pickup the current thread pointer. */ + TX_THREAD_GET_CURRENT(thread_ptr); + + /* Get the system state. */ + system_state = TX_THREAD_GET_SYSTEM_STATE(); + + /* Make sure it is not NULL. */ + if (thread_ptr != TX_NULL) + { + + /* Thread is running... make sure the call is from the thread context. */ + if (system_state == 0) + { + + /* Yes, now setup the FP enable flag in the TX_THREAD structure. */ + thread_ptr -> tx_thread_fp_enable = TX_TRUE; + } + } +} + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_interrupt_control.S b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_control.S new file mode 100644 index 00000000..1096b0b8 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_control.S @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/*#define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* UINT _tx_thread_interrupt_control(UINT new_posture) +{ */ + .global _tx_thread_interrupt_control + .type _tx_thread_interrupt_control, @function +_tx_thread_interrupt_control: + + /* Pickup current interrupt lockout posture. */ + + MRS x1, DAIF // Pickup current interrupt posture + + /* Apply the new interrupt posture. */ + + MSR DAIF, x0 // Set new interrupt posture + MOV x0, x1 // Setup return value + RET // Return to caller +/* } */ + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_interrupt_disable.S b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_disable.S new file mode 100644 index 00000000..fb865d66 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_disable.S @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_disable Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for disabling interrupts */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* UINT _tx_thread_interrupt_disable(void) +{ */ + .global _tx_thread_interrupt_disable + .type _tx_thread_interrupt_disable, @function +_tx_thread_interrupt_disable: + + /* Pickup current interrupt lockout posture. */ + + MRS x0, DAIF // Pickup current interrupt lockout posture + + /* Mask interrupts. */ + + MSR DAIFSet, 0x3 // Lockout interrupts + RET // Return to caller +/* } */ + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_interrupt_restore.S b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_restore.S new file mode 100644 index 00000000..336f54f8 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_interrupt_restore.S @@ -0,0 +1,85 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_restore Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for restoring interrupts to the state */ +/* returned by a previous _tx_thread_interrupt_disable call. */ +/* */ +/* INPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* UINT _tx_thread_interrupt_restore(UINT old_posture) +{ */ + .global _tx_thread_interrupt_restore + .type _tx_thread_interrupt_restore, @function +_tx_thread_interrupt_restore: + + /* Restore the old interrupt posture. */ + + MSR DAIF, x0 // Setup the old posture + RET // Return to caller + +/* } */ + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_schedule.S b/ports/cortex_a5x/ac6/src/tx_thread_schedule.S new file mode 100644 index 00000000..7b4e7ff4 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_schedule.S @@ -0,0 +1,240 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +*/ + +/* .set ENABLE_ARM_FP,1 */ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* 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 */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_schedule(VOID) +{ */ + .global _tx_thread_schedule + .type _tx_thread_schedule, @function +_tx_thread_schedule: + + /* Enable interrupts. */ + + MSR DAIFClr, 0x3 // Enable interrupts + + /* Wait for a thread to execute. */ + /* do + { */ + + LDR x1, =_tx_thread_execute_ptr // Address of thread execute ptr + +.ifdef TX_ENABLE_WFI +__tx_thread_schedule_loop: + LDR x0, [x1, #0] // Pickup next thread to execute + CMP x0, #0 // Is it NULL? + BNE _tx_thread_schedule_thread // + WFI // + B __tx_thread_schedule_loop // Keep looking for a thread +_tx_thread_schedule_thread: +.else +__tx_thread_schedule_loop: + LDR x0, [x1, #0] // Pickup next thread to execute + CMP x0, #0 // Is it NULL? + BEQ __tx_thread_schedule_loop // If so, keep looking for a thread +.endif + + /* } + while(_tx_thread_execute_ptr == TX_NULL); */ + + /* Yes! We have a thread to execute. Lockout interrupts and + transfer control to it. */ + + MSR DAIFSet, 0x3 // Lockout interrupts + + /* Setup the current thread pointer. */ + /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ + + LDR x1, =_tx_thread_current_ptr // Pickup address of current thread + STR x0, [x1, #0] // Setup current thread pointer + + /* Increment the run count for this thread. */ + /* _tx_thread_current_ptr -> tx_thread_run_count++; */ + + LDR w2, [x0, #4] // Pickup run counter + LDR w3, [x0, #36] // Pickup time-slice for this thread + ADD w2, w2, #1 // Increment thread run-counter + STR w2, [x0, #4] // Store the new run counter + + /* Setup time-slice, if present. */ + /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ + + LDR x2, =_tx_timer_time_slice // Pickup address of time slice + // variable + LDR x4, [x0, #8] // Switch stack pointers + MOV sp, x4 // + STR w3, [x2, #0] // Setup time-slice + +.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + /* Call the thread entry function to indicate the thread is executing. */ + + MOV x19, x0 // Save x0 + BL _tx_execution_thread_enter // Call the thread execution enter function + MOV x0, x19 // Restore x0 +.endif + + /* Switch to the thread's stack. */ + /* sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ + + /* Determine if an interrupt frame or a synchronous task suspension frame + is present. */ + + LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1 + CMP x5, #0 // Check for synchronous context switch (ELR_EL1 = NULL) + BEQ _tx_solicited_return +.ifdef EL1 + MSR SPSR_EL1, x4 // Setup SPSR for return + MSR ELR_EL1, x5 // Setup point of interrupt +.else +.ifdef EL2 + MSR SPSR_EL2, x4 // Setup SPSR for return + MSR ELR_EL2, x5 // Setup point of interrupt +.else + MSR SPSR_EL3, x4 // Setup SPSR for return + MSR ELR_EL3, x5 // Setup point of interrupt +.endif +.endif +.ifdef ENABLE_ARM_FP + LDR w1, [x0, #248] // Pickup FP enable flag + CMP w1, #0 // Is FP enabled? + BEQ _skip_interrupt_fp_restore // No, skip FP restore + LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR + MSR FPSR, x0 // Recover FPSR + MSR FPCR, x1 // Recover FPCR + LDP q30, q31, [sp], #32 // Recover q30, q31 + LDP q28, q29, [sp], #32 // Recover q28, q29 + LDP q26, q27, [sp], #32 // Recover q26, q27 + LDP q24, q25, [sp], #32 // Recover q24, q25 + LDP q22, q23, [sp], #32 // Recover q22, q23 + LDP q20, q21, [sp], #32 // Recover q20, q21 + LDP q18, q19, [sp], #32 // Recover q18, q19 + LDP q16, q17, [sp], #32 // Recover q16, q17 + LDP q14, q15, [sp], #32 // Recover q14, q15 + LDP q12, q13, [sp], #32 // Recover q12, q13 + LDP q10, q11, [sp], #32 // Recover q10, q11 + LDP q8, q9, [sp], #32 // Recover q8, q9 + LDP q6, q7, [sp], #32 // Recover q6, q7 + LDP q4, q5, [sp], #32 // Recover q4, q5 + LDP q2, q3, [sp], #32 // Recover q2, q3 + LDP q0, q1, [sp], #32 // Recover q0, q1 +_skip_interrupt_fp_restore: +.endif + LDP x28, x29, [sp], #16 // Recover x28 + LDP x26, x27, [sp], #16 // Recover x26, x27 + LDP x24, x25, [sp], #16 // Recover x24, x25 + LDP x22, x23, [sp], #16 // Recover x22, x23 + LDP x20, x21, [sp], #16 // Recover x20, x21 + LDP x18, x19, [sp], #16 // Recover x18, x19 + LDP x16, x17, [sp], #16 // Recover x16, x17 + LDP x14, x15, [sp], #16 // Recover x14, x15 + LDP x12, x13, [sp], #16 // Recover x12, x13 + LDP x10, x11, [sp], #16 // Recover x10, x11 + LDP x8, x9, [sp], #16 // Recover x8, x9 + LDP x6, x7, [sp], #16 // Recover x6, x7 + LDP x4, x5, [sp], #16 // Recover x4, x5 + LDP x2, x3, [sp], #16 // Recover x2, x3 + LDP x0, x1, [sp], #16 // Recover x0, x1 + LDP x29, x30, [sp], #16 // Recover x29, x30 + ERET // Return to point of interrupt + +_tx_solicited_return: + +.ifdef ENABLE_ARM_FP + LDR w1, [x0, #248] // Pickup FP enable flag + CMP w1, #0 // Is FP enabled? + BEQ _skip_solicited_fp_restore // No, skip FP restore + LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR + MSR FPSR, x0 // Recover FPSR + MSR FPCR, x1 // Recover FPCR + LDP q14, q15, [sp], #32 // Recover q14, q15 + LDP q12, q13, [sp], #32 // Recover q12, q13 + LDP q10, q11, [sp], #32 // Recover q10, q11 + LDP q8, q9, [sp], #32 // Recover q8, q9 +_skip_solicited_fp_restore: +.endif + LDP x27, x28, [sp], #16 // Recover x27, x28 + LDP x25, x26, [sp], #16 // Recover x25, x26 + LDP x23, x24, [sp], #16 // Recover x23, x24 + LDP x21, x22, [sp], #16 // Recover x21, x22 + LDP x19, x20, [sp], #16 // Recover x19, x20 + LDP x29, x30, [sp], #16 // Recover x29, x30 + MSR DAIF, x4 // Recover DAIF + RET // Return to caller +/* } */ + + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_stack_build.S b/ports/cortex_a5x/ac6/src/tx_thread_stack_build.S new file mode 100644 index 00000000..cd8609f2 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_stack_build.S @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +*/ + + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +{ */ + .global _tx_thread_stack_build + .type _tx_thread_stack_build, @function +_tx_thread_stack_build: + + + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the Cortex-A5x should look like the following after it is built: + + Stack Top: SSPR Initial SSPR + ELR Point of interrupt + x28 Initial value for x28 + not used Not used + x26 Initial value for x26 + x27 Initial value for x27 + x24 Initial value for x24 + x25 Initial value for x25 + x22 Initial value for x22 + x23 Initial value for x23 + x20 Initial value for x20 + x21 Initial value for x21 + x18 Initial value for x18 + x19 Initial value for x19 + x16 Initial value for x16 + x17 Initial value for x17 + x14 Initial value for x14 + x15 Initial value for x15 + x12 Initial value for x12 + x13 Initial value for x13 + x10 Initial value for x10 + x11 Initial value for x11 + x8 Initial value for x8 + x9 Initial value for x9 + x6 Initial value for x6 + x7 Initial value for x7 + x4 Initial value for x4 + x5 Initial value for x5 + x2 Initial value for x2 + x3 Initial value for x3 + x0 Initial value for x0 + x1 Initial value for x1 + x29 Initial value for x29 (frame pointer) + x30 Initial value for x30 (link register) + 0 For stack backtracing + + Stack Bottom: (higher memory address) */ + + LDR x4, [x0, #24] // Pickup end of stack area + BIC x4, x4, #0xF // Ensure 16-byte alignment + + /* Actually build the stack frame. */ + + MOV x2, #0 // Build clear value + MOV x3, #0 // + + STP x2, x3, [x4, #-16]! // Set backtrace to 0 + STP x2, x3, [x4, #-16]! // Set initial x29, x30 + STP x2, x3, [x4, #-16]! // Set initial x0, x1 + STP x2, x3, [x4, #-16]! // Set initial x2, x3 + STP x2, x3, [x4, #-16]! // Set initial x4, x5 + STP x2, x3, [x4, #-16]! // Set initial x6, x7 + STP x2, x3, [x4, #-16]! // Set initial x8, x9 + STP x2, x3, [x4, #-16]! // Set initial x10, x11 + STP x2, x3, [x4, #-16]! // Set initial x12, x13 + STP x2, x3, [x4, #-16]! // Set initial x14, x15 + STP x2, x3, [x4, #-16]! // Set initial x16, x17 + STP x2, x3, [x4, #-16]! // Set initial x18, x19 + STP x2, x3, [x4, #-16]! // Set initial x20, x21 + STP x2, x3, [x4, #-16]! // Set initial x22, x23 + STP x2, x3, [x4, #-16]! // Set initial x24, x25 + STP x2, x3, [x4, #-16]! // Set initial x26, x27 + STP x2, x3, [x4, #-16]! // Set initial x28 +.ifdef EL1 + MOV x2, #0x5 // Build initial SPSR (EL1) +.else +.ifdef EL2 + MOV x2, #0x9 // Build initial SPSR (EL2) +.else + MOV x2, #0xD // Build initial SPSR (EL3) +.endif +.endif + MOV x3, x1 // Build initial ELR + STP x2, x3, [x4, #-16]! // Set initial SPSR & ELR + + /* Setup stack pointer. */ + /* thread_ptr -> tx_thread_stack_ptr = x2; */ + + STR x4, [x0, #8] // Save stack pointer in thread's + RET // Return to caller + +/* } */ + + diff --git a/ports/cortex_a5x/ac6/src/tx_thread_system_return.S b/ports/cortex_a5x/ac6/src/tx_thread_system_return.S new file mode 100644 index 00000000..5106a801 --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_thread_system_return.S @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +*/ + +/* .set ENABLE_ARM_FP,1 */ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the 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 */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_thread_system_return(VOID) +{ */ + .global _tx_thread_system_return + .type _tx_thread_system_return, @function +_tx_thread_system_return: +; +; /* Save minimal context on the stack. */ +; + MRS x0, DAIF // Pickup DAIF + MSR DAIFSet, 0x3 // Lockout interrupts + STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register) + STP x19, x20, [sp, #-16]! // Save x19, x20 + STP x21, x22, [sp, #-16]! // Save x21, x22 + STP x23, x24, [sp, #-16]! // Save x23, x24 + STP x25, x26, [sp, #-16]! // Save x25, x26 + STP x27, x28, [sp, #-16]! // Save x27, x28 + LDR x5, =_tx_thread_current_ptr // Pickup address of current ptr + LDR x6, [x5, #0] // Pickup current thread pointer + +.ifdef ENABLE_ARM_FP + LDR w7, [x6, #248] // Pickup FP enable flag + CMP w7, #0 // Is FP enabled? + BEQ _skip_fp_save // No, skip FP save + STP q8, q9, [sp, #-32]! // Save q8, q9 + STP q10, q11, [sp, #-32]! // Save q10, q11 + STP q12, q13, [sp, #-32]! // Save q12, q13 + STP q14, q15, [sp, #-32]! // Save q14, q15 + MRS x2, FPSR // Pickup FPSR + MRS x3, FPCR // Pickup FPCR + STP x2, x3, [sp, #-16]! // Save FPSR, FPCR +_skip_fp_save: +.endif + + MOV x1, #0 // Clear x1 + STP x0, x1, [sp, #-16]! // Save DAIF and clear value for ELR_EK1 + +.ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + + /* Call the thread exit function to indicate the thread is no longer executing. */ + + MOV x19, x5 // Save x5 + MOV x20, x6 // Save x6 + BL _tx_execution_thread_exit // Call the thread exit function + MOV x5, x19 // Restore x5 + MOV x6, x20 // Restore x6 +.endif + + LDR x2, =_tx_timer_time_slice // Pickup address of time slice + LDR w1, [x2, #0] // Pickup current time slice + + /* Save current stack and switch to system stack. */ + /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ + /* sp = _tx_thread_system_stack_ptr; */ + + MOV x4, sp // + STR x4, [x6, #8] // Save thread stack pointer + LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack + LDR x4, [x3, #0] // Pickup system stack pointer + MOV sp, x4 // Setup system stack pointer + + /* Determine if the time-slice is active. */ + /* if (_tx_timer_time_slice) + { */ + + MOV x4, #0 // Build clear value + CMP w1, #0 // Is a time-slice active? + BEQ __tx_thread_dont_save_ts // No, don't save the time-slice + + /* Save the current remaining time-slice. */ + /* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; + _tx_timer_time_slice = 0; */ + + STR w4, [x2, #0] // Clear time-slice + STR w1, [x6, #36] // Store current time-slice + + /* } */ +__tx_thread_dont_save_ts: + + /* Clear the current thread pointer. */ + /* _tx_thread_current_ptr = TX_NULL; */ + + STR x4, [x5, #0] // Clear current thread pointer + + B _tx_thread_schedule // Jump to scheduler! + +/* } */ + + diff --git a/ports/cortex_a5x/ac6/src/tx_timer_interrupt.S b/ports/cortex_a5x/ac6/src/tx_timer_interrupt.S new file mode 100644 index 00000000..1559352e --- /dev/null +++ b/ports/cortex_a5x/ac6/src/tx_timer_interrupt.S @@ -0,0 +1,240 @@ +/**************************************************************************/ +/* */ +/* 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 */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* #define TX_SOURCE_CODE */ + + +/* Include necessary system files. */ + +/* +#include "tx_api.h" +#include "tx_timer.h" +#include "tx_thread.h" +*/ + + .text + .align 3 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Cortex-A5x/ARM */ +/* 6.0.1 */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* interrupt context save/restore functions are called along with the */ +/* expiration functions. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 06-30-2020 William E. Lamie Initial Version 6.0.1 */ +/* */ +/**************************************************************************/ +/* VOID _tx_timer_interrupt(VOID) +{ */ + .global _tx_timer_interrupt + .type _tx_timer_interrupt, @function +_tx_timer_interrupt: + + /* Upon entry to this routine, it is assumed that context save has already + been called, and therefore the compiler scratch registers are available + for use. */ + + /* Increment the system clock. */ + /* _tx_timer_system_clock++; */ + + LDR x1, =_tx_timer_system_clock // Pickup address of system clock + LDR w0, [x1, #0] // Pickup system clock + ADD w0, w0, #1 // Increment system clock + STR w0, [x1, #0] // Store new system clock + + /* Test for time-slice expiration. */ + /* if (_tx_timer_time_slice) + { */ + + LDR x3, =_tx_timer_time_slice // Pickup address of time-slice + LDR w2, [x3, #0] // Pickup time-slice + CMP w2, #0 // Is it non-active? + BEQ __tx_timer_no_time_slice // Yes, skip time-slice processing + + /* Decrement the time_slice. */ + /* _tx_timer_time_slice--; */ + + SUB w2, w2, #1 // Decrement the time-slice + STR w2, [x3, #0] // Store new time-slice value + + /* Check for expiration. */ + /* if (__tx_timer_time_slice == 0) */ + + CMP w2, #0 // Has it expired? + BNE __tx_timer_no_time_slice // No, skip expiration processing + + /* Set the time-slice expired flag. */ + /* _tx_timer_expired_time_slice = TX_TRUE; */ + + LDR x3, =_tx_timer_expired_time_slice // Pickup address of expired flag + MOV w0, #1 // Build expired value + STR w0, [x3, #0] // Set time-slice expiration flag + + /* } */ + +__tx_timer_no_time_slice: + + /* Test for timer expiration. */ + /* if (*_tx_timer_current_ptr) + { */ + + LDR x1, =_tx_timer_current_ptr // Pickup current timer pointer addr + LDR x0, [x1, #0] // Pickup current timer + LDR x2, [x0, #0] // Pickup timer list entry + CMP x2, #0 // Is there anything in the list? + BEQ __tx_timer_no_timer // No, just increment the timer + + /* Set expiration flag. */ + /* _tx_timer_expired = TX_TRUE; */ + + LDR x3, =_tx_timer_expired // Pickup expiration flag address + MOV w2, #1 // Build expired value + STR w2, [x3, #0] // Set expired flag + B __tx_timer_done // Finished timer processing + + /* } + else + { */ +__tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + /* _tx_timer_current_ptr++; */ + + ADD x0, x0, #8 // Move to next timer + + /* Check for wrap-around. */ + /* if (_tx_timer_current_ptr == _tx_timer_list_end) */ + + LDR x3, =_tx_timer_list_end // Pickup addr of timer list end + LDR x2, [x3, #0] // Pickup list end + CMP x0, x2 // Are we at list end? + BNE __tx_timer_skip_wrap // No, skip wrap-around logic + + /* Wrap to beginning of list. */ + /* _tx_timer_current_ptr = _tx_timer_list_start; */ + + LDR x3, =_tx_timer_list_start // Pickup addr of timer list start + LDR x0, [x3, #0] // Set current pointer to list start + +__tx_timer_skip_wrap: + + STR x0, [x1, #0] // Store new current timer pointer + /* } */ + +__tx_timer_done: + + + /* See if anything has expired. */ + /* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + { */ + + LDR x3, =_tx_timer_expired_time_slice // Pickup addr of expired flag + LDR w2, [x3, #0] // Pickup time-slice expired flag + CMP w2, #0 // Did a time-slice expire? + BNE __tx_something_expired // If non-zero, time-slice expired + LDR x1, =_tx_timer_expired // Pickup addr of other expired flag + LDR w0, [x1, #0] // Pickup timer expired flag + CMP w0, #0 // Did a timer expire? + BEQ __tx_timer_nothing_expired // No, nothing expired + +__tx_something_expired: + + + STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register) + + /* Did a timer expire? */ + /* if (_tx_timer_expired) + { */ + + LDR x1, =_tx_timer_expired // Pickup addr of expired flag + LDR w0, [x1, #0] // Pickup timer expired flag + CMP w0, #0 // Check for timer expiration + BEQ __tx_timer_dont_activate // If not set, skip timer activation + + /* Process timer expiration. */ + /* _tx_timer_expiration_process(); */ + + BL _tx_timer_expiration_process // Call the timer expiration handling routine + + /* } */ +__tx_timer_dont_activate: + + /* Did time slice expire? */ + /* if (_tx_timer_expired_time_slice) + { */ + + LDR x3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired + LDR w2, [x3, #0] // Pickup the actual flag + CMP w2, #0 // See if the flag is set + BEQ __tx_timer_not_ts_expiration // No, skip time-slice processing + + /* Time slice interrupted thread. */ + /* _tx_thread_time_slice(); */ + + BL _tx_thread_time_slice // Call time-slice processing + + /* } */ + +__tx_timer_not_ts_expiration: + + LDP x29, x30, [sp], #16 // Recover x29, x30 + /* } */ + +__tx_timer_nothing_expired: + + RET // Return to caller + +/* } */ + + |
