mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2025-11-16 12:34:48 +00:00
Release 6.1.7
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
<?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.1186660388">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.1186660388" 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="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.1186660388" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug" postbuildStep="">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.1186660388." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.debug.2059027187" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.debug">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.toolchain.v6.base.options.debug.level.217899897" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1952359845" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R4.VFPv3_D16" valueType="string"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.floatabi.2083363025" name="Float ABI" superClass="com.arm.toolchain.v6.base.options.floatabi" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.inst.214405138" name="Instruction set" superClass="com.arm.toolchain.v6.base.options.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.debug.1186660388..1840465310" name=""/>
|
||||
<builder buildPath="${workspace_loc:/sample_threadx_module}/Debug" id="com.arm.toolchain.v6.builder.712205487" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/>
|
||||
<tool id="com.arm.tool.c.compiler.v6.2054850494" 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.1593499563" 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.558177784" 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.cpu.1528797782" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.target.2107191754" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.fpu.701656758" name="FPU (-mfpu)" superClass="com.arm.tool.c.compiler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.floatabi.271588144" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.c.compiler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.inst.1826434500" name="Instruction set" superClass="com.arm.tool.c.compiler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.incpath.1401908599" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/txm/inc_generic}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/txm/inc_generic_modules}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/txm/inc_port}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.flags.121551369" name="Other flags" superClass="com.arm.tool.c.compiler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="-fropi"/>
|
||||
<listOptionValue builtIn="false" value="-frwpi"/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings.1260481240" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.294190860" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.1360199906" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.22094800" 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.1119785101" 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.1584629976" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.1445475633" 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.1996877403" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.1169848349" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.target.1621759525" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" useByScannerDiscovery="false" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.fpu.1052186290" name="FPU (-mfpu)" superClass="com.arm.tool.assembler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.floatabi.621797848" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.assembler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.inst.669141109" name="Instruction set" superClass="com.arm.tool.assembler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.incpath.46636479" name="Include path (-I)" superClass="com.arm.tool.assembler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/txm}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.flags.1723710627" name="Other flags" superClass="com.arm.tool.assembler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="-frwpi"/>
|
||||
<listOptionValue builtIn="false" value="-fropi"/>
|
||||
</option>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.705473083" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.1069019142" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6">
|
||||
<option id="com.arm.tool.c.linker.implicit.libs.411858467" name="Implicit other library files" superClass="com.arm.tool.c.linker.implicit.libs" useByScannerDiscovery="false" valueType="libs">
|
||||
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value=""${workspace_loc:/txm/Debug/txm.a}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.linker.option.entry.2143658488" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" useByScannerDiscovery="false" value="_txm_module_thread_shell_entry" valueType="string"/>
|
||||
<option id="com.arm.tool.c.linker.option.predefine.1247653322" name="Predefine (--pd)" superClass="com.arm.tool.c.linker.option.predefine" useByScannerDiscovery="true"/>
|
||||
<option id="com.arm.tool.c.linker.option.flags.1650736668" name="Other flags" superClass="com.arm.tool.c.linker.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="--first txm_module_preamble.o"/>
|
||||
<listOptionValue builtIn="false" value="--ro 0x00100000"/>
|
||||
<listOptionValue builtIn="false" value="--ropi"/>
|
||||
<listOptionValue builtIn="false" value="--rwpi"/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.linker.option.redirectoutput.208933002" name="Redirect diagnostics output to file (--list)" superClass="com.arm.tool.c.linker.option.redirectoutput" useByScannerDiscovery="false" value="" valueType="string"/>
|
||||
<option id="com.arm.tool.c.linker.option.sizes.1595432024" name="List code and data sizes of output image (--info=sizes)" superClass="com.arm.tool.c.linker.option.sizes" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.linker.option.elim.1398313860" name="List unused sections that are eliminated (--info=unused)" superClass="com.arm.tool.c.linker.option.elim" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.linker.option.totals.1098945540" name="List total code and data sizes of output image (--info=totals)" superClass="com.arm.tool.c.linker.option.totals" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.librarian.v6.17867471" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings">
|
||||
<externalSettings containerId="tx;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier">
|
||||
<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>
|
||||
<externalSettings containerId="txm;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier">
|
||||
<externalSetting>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/txm"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/txm/Debug"/>
|
||||
<entry flags="RESOLVED" kind="libraryFile" name="txm" srcPrefixMapping="" srcRootPath=""/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
</storageModule>
|
||||
</cconfiguration>
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.exe.release.1059742195">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.release.1059742195" 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="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.release.1059742195" name="Release" parent="com.arm.eclipse.build.config.v6.exe.release">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.release.1059742195." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.release.193865725" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.release">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.toolchain.v6.base.options.debug.level.245795922" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.release.1059742195..238205684" name=""/>
|
||||
<builder buildPath="${workspace_loc:/sample_threadx_module}/Release" id="com.arm.toolchain.v6.builder.1520240122" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/>
|
||||
<tool id="com.arm.tool.c.compiler.v6.1225859893" 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.1899903412" 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.348399030" 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.772104434" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.422075046" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.879947257" 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.1104950385" 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.176097568" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.1910026527" 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.891339047" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.344668889" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.20284280" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6"/>
|
||||
<tool id="com.arm.tool.librarian.v6.775202115" 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_module.com.arm.eclipse.build.project.v6.exe.1790254349" 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"/>
|
||||
<storageModule moduleId="com.arm.projectSettings" version="5.25"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
</cproject>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sample_threadx_module</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>tx</project>
|
||||
<project>txm</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="com.arm.eclipse.build.config.v6.exe.debug.1186660388" 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="1218969334819235502" 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.1059742195" 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="1208898303067000398" 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>
|
||||
@@ -0,0 +1,425 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel running as a module. It includes
|
||||
examples of eight threads of different priorities, using a message queue, semaphore, mutex,
|
||||
event flags group, byte pool, and block pool. */
|
||||
|
||||
/* Specify that this is a module! */
|
||||
|
||||
#define TXM_MODULE
|
||||
|
||||
|
||||
/* Include the ThreadX module definitions. */
|
||||
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define constants. */
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define the pool space in the bss section of the module. ULONG is used to
|
||||
get the word alignment. */
|
||||
|
||||
ULONG demo_module_pool_space[DEMO_BYTE_POOL_SIZE / 4];
|
||||
|
||||
|
||||
/* 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 = 0x12;
|
||||
ULONG thread_1_counter = 0x34;
|
||||
ULONG thread_2_counter = 0x56;
|
||||
ULONG thread_3_counter = 0x78;
|
||||
ULONG thread_4_counter = 0x9A;
|
||||
ULONG thread_5_counter = 0xBC;
|
||||
ULONG thread_6_counter = 0xDE;
|
||||
ULONG thread_7_counter = 0xEF;
|
||||
ULONG semaphore_0_puts;
|
||||
ULONG event_0_sets;
|
||||
ULONG queue_0_sends;
|
||||
|
||||
ULONG thread_1_messages_sent;
|
||||
ULONG thread_2_messages_received;
|
||||
|
||||
/* 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);
|
||||
|
||||
void semaphore_0_notify(TX_SEMAPHORE *semaphore_ptr)
|
||||
{
|
||||
|
||||
if (semaphore_ptr == semaphore_0)
|
||||
semaphore_0_puts++;
|
||||
}
|
||||
|
||||
|
||||
void event_0_notify(TX_EVENT_FLAGS_GROUP *event_flag_group_ptr)
|
||||
{
|
||||
|
||||
if (event_flag_group_ptr == event_flags_0)
|
||||
event_0_sets++;
|
||||
}
|
||||
|
||||
|
||||
void queue_0_notify(TX_QUEUE *queue_ptr)
|
||||
{
|
||||
|
||||
if (queue_ptr == queue_0)
|
||||
queue_0_sends++;
|
||||
}
|
||||
|
||||
|
||||
/* Define the module start function. */
|
||||
|
||||
void demo_module_start(ULONG id)
|
||||
{
|
||||
|
||||
CHAR *pointer;
|
||||
|
||||
/* Allocate all the objects. In MMU mode, modules cannot allocate control blocks within
|
||||
their own memory area so they cannot corrupt the resident portion of ThreadX by overwriting
|
||||
the control block(s). */
|
||||
txm_module_object_allocate((void *) &thread_0, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_1, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_2, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_3, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_4, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_5, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_6, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &thread_7, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void *) &queue_0, sizeof(TX_QUEUE));
|
||||
txm_module_object_allocate((void *) &semaphore_0, sizeof(TX_SEMAPHORE));
|
||||
txm_module_object_allocate((void *) &mutex_0, sizeof(TX_MUTEX));
|
||||
txm_module_object_allocate((void *) &event_flags_0, sizeof(TX_EVENT_FLAGS_GROUP));
|
||||
txm_module_object_allocate((void *) &byte_pool_0, sizeof(TX_BYTE_POOL));
|
||||
txm_module_object_allocate((void *) &block_pool_0, sizeof(TX_BLOCK_POOL));
|
||||
|
||||
/* Create a byte memory pool from which to allocate the thread stacks. */
|
||||
tx_byte_pool_create(byte_pool_0, "module byte pool 0", demo_module_pool_space, 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
|
||||
|
||||
tx_queue_send_notify(queue_0, queue_0_notify);
|
||||
|
||||
/* Create the semaphore used by threads 3 and 4. */
|
||||
tx_semaphore_create(semaphore_0, "module semaphore 0", 1);
|
||||
|
||||
tx_semaphore_put_notify(semaphore_0, semaphore_0_notify);
|
||||
|
||||
/* Create the event flags group used by threads 1 and 5. */
|
||||
tx_event_flags_create(event_flags_0, "module event flags 0");
|
||||
|
||||
tx_event_flags_set_notify(event_flags_0, event_0_notify);
|
||||
|
||||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
|
||||
tx_mutex_create(mutex_0, "module 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, "module 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;
|
||||
|
||||
/* Test external/shared memory. */
|
||||
*(ULONG *) 0x08025000 = 0xdeadbeef;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Disable semihosting */
|
||||
#include <rt_sys.h>
|
||||
|
||||
#if (__ARMCC_VERSION < 6000000)
|
||||
#pragma import(__use_no_semihosting)
|
||||
#else
|
||||
void use_no_semihosting(void)
|
||||
{
|
||||
__asm(".global __use_no_semihosting\n\t");
|
||||
}
|
||||
#endif
|
||||
|
||||
char *$Sub$$_sys_command_string(char *cmd, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void $Sub$$_sys_exit(int return_code)
|
||||
{
|
||||
while(1);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) int $Sub$$__raise(int signal, int type)
|
||||
{
|
||||
while(1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
.text
|
||||
|
||||
/* Define common external references. */
|
||||
|
||||
.global _txm_module_thread_shell_entry
|
||||
.global demo_module_start
|
||||
.global _txm_module_callback_request_thread_entry
|
||||
.global Image$$ER_RO$$Length
|
||||
.global Image$$ER_RW$$Length
|
||||
.global Image$$ER_ZI$$ZI$$Length
|
||||
|
||||
/* Stack aligned, ROPI and RWPI, R9 used as data offset register. */
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
.eabi_attribute Tag_ABI_PCS_RO_data, 1
|
||||
.eabi_attribute Tag_ABI_PCS_R9_use, 1
|
||||
.eabi_attribute Tag_ABI_PCS_RW_data, 2
|
||||
|
||||
__txm_module_preamble:
|
||||
.word 0x4D4F4455 /* Module ID */
|
||||
.word 0x6 /* Module Major Version */
|
||||
.word 0x1 /* Module Minor Version */
|
||||
.word 32 /* Module Preamble Size in 32-bit words */
|
||||
.word 0x12345678 /* Module ID (application defined) */
|
||||
.word 0x01000001 /* Module Properties where:
|
||||
Bits 31-24: Compiler ID
|
||||
0 -> IAR
|
||||
1 -> RVDS/ARM
|
||||
2 -> GNU
|
||||
Bits 23-1: Reserved
|
||||
Bit 0: 0 -> Privileged mode execution (no MMU protection)
|
||||
1 -> User mode execution (MMU protection) */
|
||||
.word _txm_module_thread_shell_entry - __txm_module_preamble /* Module Shell Entry Point */
|
||||
.word demo_module_start - __txm_module_preamble /* Module Start Thread Entry Point */
|
||||
.word 0 /* Module Stop Thread Entry Point */
|
||||
.word 1 /* Module Start/Stop Thread Priority */
|
||||
.word 1024 /* Module Start/Stop Thread Stack Size */
|
||||
.word _txm_module_callback_request_thread_entry - __txm_module_preamble /* Module Callback Thread Entry */
|
||||
.word 1 /* Module Callback Thread Priority */
|
||||
.word 1024 /* Module Callback Thread Stack Size */
|
||||
.word 9000 /* Module Code Size */
|
||||
.word 11000 /* Module Data Size */
|
||||
.word 0 /* Reserved 0 */
|
||||
.word 0 /* Reserved 1 */
|
||||
.word 0 /* Reserved 2 */
|
||||
.word 0 /* Reserved 3 */
|
||||
.word 0 /* Reserved 4 */
|
||||
.word 0 /* Reserved 5 */
|
||||
.word 0 /* Reserved 6 */
|
||||
.word 0 /* Reserved 7 */
|
||||
.word 0 /* Reserved 8 */
|
||||
.word 0 /* Reserved 9 */
|
||||
.word 0 /* Reserved 10 */
|
||||
.word 0 /* Reserved 11 */
|
||||
.word 0 /* Reserved 12 */
|
||||
.word 0 /* Reserved 13 */
|
||||
.word 0 /* Reserved 14 */
|
||||
.word 0 /* Reserved 15 */
|
||||
@@ -0,0 +1,136 @@
|
||||
<?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.779721393">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.779721393" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<externalSettings>
|
||||
<externalSetting>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/sample_threadx"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/sample_threadx/Debug"/>
|
||||
<entry flags="RESOLVED" kind="libraryFile" name="sample_threadx" srcPrefixMapping="" srcRootPath=""/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.779721393" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.779721393." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.debug.103434698" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.debug">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.toolchain.v6.base.options.debug.level.122267120" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.727798067" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R4.VFPv3_D16" valueType="string"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.floatabi.1169109311" name="Float ABI" superClass="com.arm.toolchain.v6.base.options.floatabi" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.inst.197022885" name="Instruction set" superClass="com.arm.toolchain.v6.base.options.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.debug.779721393..127053145" name=""/>
|
||||
<builder buildPath="${workspace_loc:/sample_threadx}/Debug" id="com.arm.toolchain.v6.builder.1758911861" 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.418132421" 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.19928102" 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.337331949" 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.cpu.58215761" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.target.1459440744" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.fpu.1654602745" name="FPU (-mfpu)" superClass="com.arm.tool.c.compiler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.floatabi.1877168310" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.c.compiler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.inst.1182112443" name="Instruction set" superClass="com.arm.tool.c.compiler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.incpath.758740586" 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_port}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic_modules}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.defmac.1457716013" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false"/>
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.166957004" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.514187035" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.1802813297" 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.1205322853" 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.1437798868" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.1811190142" 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.566763408" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.1716622463" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.target.776341361" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" useByScannerDiscovery="false" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.fpu.1794164835" name="FPU (-mfpu)" superClass="com.arm.tool.assembler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.floatabi.1726500202" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.assembler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.hard" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.inst.147805472" name="Instruction set" superClass="com.arm.tool.assembler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.defmac.2087651802" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac" useByScannerDiscovery="false"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.2040825079" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.1953954901" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6">
|
||||
<option id="com.arm.tool.c.linker.option.scatter.1560645973" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" useByScannerDiscovery="false" value="../sample_threadx.scat" valueType="string"/>
|
||||
<option id="com.arm.tool.c.linker.option.entry.954936793" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" useByScannerDiscovery="false" value="Vectors" valueType="string"/>
|
||||
<option id="com.arm.tool.c.linker.libs.1433839093" name="User library files" superClass="com.arm.tool.c.linker.libs" useByScannerDiscovery="false" valueType="libs">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/Debug/tx.a}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.linker.option.sizes.1385096859" name="List code and data sizes of output image (--info=sizes)" superClass="com.arm.tool.c.linker.option.sizes" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.linker.option.imagemap.98974534" name="Generate image map (--map)" superClass="com.arm.tool.c.linker.option.imagemap" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.linker.option.redirectoutput.1754253893" name="Redirect diagnostics output to file (--list)" superClass="com.arm.tool.c.linker.option.redirectoutput" useByScannerDiscovery="false" value="map.map" valueType="string"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.librarian.v6.675978717" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry 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.exe.release.713968185">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.release.713968185" 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="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.release.713968185" name="Release" parent="com.arm.eclipse.build.config.v6.exe.release">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.release.713968185." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.release.1460511458" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.release">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.toolchain.v6.base.options.debug.level.2051889961" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.release.713968185..616485282" name=""/>
|
||||
<builder buildPath="${workspace_loc:/sample_threadx}/Release" id="com.arm.toolchain.v6.builder.870395099" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/>
|
||||
<tool id="com.arm.tool.c.compiler.v6.259065810" 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.1016945654" 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.1192425502" 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.1880078422" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.1562364562" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.162044254" 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.1518199483" 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.1403473824" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.2117272930" 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.1879820366" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.1863547577" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.1898632817" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6"/>
|
||||
<tool id="com.arm.tool.librarian.v6.74576969" 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.1139105725" 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="com.arm.projectSettings" version="5.25"/>
|
||||
<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>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sample_threadx_module_manager</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>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="com.arm.eclipse.build.config.v6.exe.debug.779721393" 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="1257603729813011790" 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.713968185" 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="1208898303067000398" 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>
|
||||
@@ -0,0 +1,239 @@
|
||||
/** GIC start **/
|
||||
/* ------------------------- Interrupt Number Definition ------------------------ */
|
||||
|
||||
#include "gic.h"
|
||||
|
||||
#define VE_R4_GIC_DISTRIBUTOR_BASE (0xAE001000UL) /*!< (PL390 GIC Distributor ) Base Address */
|
||||
#define VE_R4_GIC_INTERFACE_BASE (0xAE000000UL) /*!< (PL390 GIC CPU Interface) Base Address */
|
||||
|
||||
#define GICDistributor ((GICDistributor_Type *) VE_R4_GIC_DISTRIBUTOR_BASE ) /*!< GIC Distributor configuration struct */
|
||||
#define GICInterface ((GICInterface_Type *) VE_R4_GIC_INTERFACE_BASE ) /*!< GIC Interface configuration struct */
|
||||
|
||||
/* Globals for use of post-scatterloading code that must access GIC */
|
||||
const uint32_t GICDistributor_BASE = VE_R4_GIC_DISTRIBUTOR_BASE;
|
||||
const uint32_t GICInterface_BASE = VE_R4_GIC_INTERFACE_BASE;
|
||||
|
||||
#if 0
|
||||
|
||||
void GIC_SetICDICFR (const uint32_t *ICDICFRn)
|
||||
{
|
||||
uint32_t i, num_irq;
|
||||
|
||||
//Get the maximum number of interrupts that the GIC supports
|
||||
num_irq = 32 * ((GIC_DistributorInfo() & 0x1f) + 1);
|
||||
|
||||
for (i = 0; i < (num_irq/16); i++)
|
||||
{
|
||||
GICDistributor->ICDISPR[i] = *ICDICFRn++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GIC_DistributorImplementer(void)
|
||||
{
|
||||
return (uint32_t)(GICDistributor->ICDIIDR);
|
||||
}
|
||||
|
||||
uint32_t GIC_GetTarget(IRQn_Type IRQn)
|
||||
{
|
||||
char* field = (char*)&(GICDistributor->ICDIPTR[IRQn / 4]);
|
||||
field += IRQn % 4;
|
||||
return ((uint32_t)*field & 0xf);
|
||||
}
|
||||
|
||||
IRQn_Type GIC_AcknowledgePending(void)
|
||||
{
|
||||
return (IRQn_Type)(GICInterface->ICCIAR);
|
||||
}
|
||||
|
||||
uint32_t GIC_GetBinaryPoint(uint32_t binary_point)
|
||||
{
|
||||
return (uint32_t)GICInterface->ICCBPR;
|
||||
}
|
||||
|
||||
uint32_t GIC_GetIRQStatus(IRQn_Type IRQn)
|
||||
{
|
||||
uint32_t pending, active;
|
||||
|
||||
active = ((GICDistributor->ICDABR[IRQn / 32]) >> (IRQn % 32)) & 0x1;
|
||||
pending =((GICDistributor->ICDISPR[IRQn / 32]) >> (IRQn % 32)) & 0x1;
|
||||
|
||||
return ((active<<1) | pending);
|
||||
}
|
||||
|
||||
void GIC_SendSGI(IRQn_Type IRQn, uint32_t target_list, uint32_t filter_list)
|
||||
{
|
||||
GICDistributor->ICDSGIR = ((filter_list & 0x3) << 24) | ((target_list & 0xff) << 16) | (IRQn & 0xf);
|
||||
}
|
||||
|
||||
void GIC_EndInterrupt(IRQn_Type IRQn)
|
||||
{
|
||||
GICInterface->ICCEOIR = IRQn;
|
||||
}
|
||||
|
||||
void GIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
GICDistributor->ICDISPR[IRQn / 32] = 1 << (IRQn % 32);
|
||||
}
|
||||
|
||||
void GIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
GICDistributor->ICDICPR[IRQn / 32] = 1 << (IRQn % 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void GIC_EnableDistributor(void)
|
||||
{
|
||||
GICDistributor->ICDDCR |= 1; //enable distributor
|
||||
}
|
||||
|
||||
void GIC_DisableDistributor(void)
|
||||
{
|
||||
GICDistributor->ICDDCR &=~1; //disable distributor
|
||||
}
|
||||
|
||||
void GIC_SetTarget(IRQn_Type IRQn, uint32_t cpu_target)
|
||||
{
|
||||
char* field = (char*)&(GICDistributor->ICDIPTR[IRQn / 4]);
|
||||
field += IRQn % 4;
|
||||
*field = (char)cpu_target & 0xf;
|
||||
}
|
||||
|
||||
void GIC_EnableInterface(void)
|
||||
{
|
||||
GICInterface->ICCICR |= 1; //enable interface
|
||||
}
|
||||
|
||||
void GIC_DisableInterface(void)
|
||||
{
|
||||
GICInterface->ICCICR &=~1; //disable distributor
|
||||
}
|
||||
|
||||
void GIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
GICDistributor->ICDISER[IRQn / 32] = 1 << (IRQn % 32);
|
||||
}
|
||||
|
||||
void GIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
GICDistributor->ICDICER[IRQn / 32] = 1 << (IRQn % 32);
|
||||
}
|
||||
|
||||
uint32_t GIC_DistributorInfo(void)
|
||||
{
|
||||
return (uint32_t)(GICDistributor->ICDICTR);
|
||||
}
|
||||
|
||||
|
||||
void GIC_SetLevelModel(IRQn_Type IRQn, int8_t edge_level, int8_t model)
|
||||
{ // Word-size read/writes must be used to access this register
|
||||
volatile uint32_t * field = &(GICDistributor->ICDICFR[IRQn / 16]);
|
||||
unsigned bit_shift = (IRQn % 16)<<1;
|
||||
unsigned int save_word;
|
||||
|
||||
save_word = *field;
|
||||
save_word &= (~(3 << bit_shift));
|
||||
|
||||
*field = (save_word | (((edge_level<<1) | model) << bit_shift));
|
||||
}
|
||||
|
||||
void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
char* field = (char*)&(GICDistributor->ICDIPR[IRQn / 4]);
|
||||
field += IRQn % 4;
|
||||
*field = (char)priority;
|
||||
}
|
||||
|
||||
uint32_t GIC_GetPriority(IRQn_Type IRQn)
|
||||
{
|
||||
char* field = (char*)&(GICDistributor->ICDIPR[IRQn / 4]);
|
||||
field += IRQn % 4;
|
||||
return (uint32_t)*field;
|
||||
}
|
||||
|
||||
void GIC_InterfacePriorityMask(uint32_t priority)
|
||||
{
|
||||
GICInterface->ICCPMR = priority & 0xff; //set priority mask
|
||||
}
|
||||
|
||||
void GIC_SetBinaryPoint(uint32_t binary_point)
|
||||
{
|
||||
GICInterface->ICCBPR = binary_point & 0x07; //set binary point
|
||||
}
|
||||
|
||||
void GIC_DistInit(void)
|
||||
{
|
||||
IRQn_Type i;
|
||||
uint32_t num_irq = 0;
|
||||
uint32_t priority_field;
|
||||
|
||||
//A reset sets all bits in the ICDISRs corresponding to the SPIs to 0,
|
||||
//configuring all of the interrupts as Secure.
|
||||
|
||||
//Disable interrupt forwarding
|
||||
GIC_DisableDistributor();
|
||||
//Get the maximum number of interrupts that the GIC supports
|
||||
num_irq = 32 * ((GIC_DistributorInfo() & 0x1f) + 1);
|
||||
|
||||
/* Priority level is implementation defined.
|
||||
To determine the number of priority bits implemented write 0xFF to an ICDIPR
|
||||
priority field and read back the value stored.*/
|
||||
GIC_SetPriority((IRQn_Type)0, 0xff);
|
||||
priority_field = GIC_GetPriority((IRQn_Type)0);
|
||||
|
||||
for (i = (IRQn_Type)32; i < num_irq; i++)
|
||||
{
|
||||
//Disable the SPI interrupt
|
||||
GIC_DisableIRQ(i);
|
||||
//Set level-sensitive and 1-N model
|
||||
GIC_SetLevelModel(i, 0, 1);
|
||||
//Set priority
|
||||
GIC_SetPriority(i, priority_field/2);
|
||||
//Set target list to CPU0
|
||||
GIC_SetTarget(i, 1);
|
||||
}
|
||||
//Enable distributor
|
||||
GIC_EnableDistributor();
|
||||
}
|
||||
|
||||
void GIC_CPUInterfaceInit(void)
|
||||
{
|
||||
IRQn_Type i;
|
||||
uint32_t priority_field;
|
||||
|
||||
//A reset sets all bits in the ICDISRs corresponding to the SPIs to 0,
|
||||
//configuring all of the interrupts as Secure.
|
||||
|
||||
//Disable interrupt forwarding
|
||||
GIC_DisableInterface();
|
||||
|
||||
/* Priority level is implementation defined.
|
||||
To determine the number of priority bits implemented write 0xFF to an ICDIPR
|
||||
priority field and read back the value stored.*/
|
||||
GIC_SetPriority((IRQn_Type)0, 0xff);
|
||||
priority_field = GIC_GetPriority((IRQn_Type)0);
|
||||
|
||||
//SGI and PPI
|
||||
for (i = (IRQn_Type)0; i < 32; i++)
|
||||
{
|
||||
//Set level-sensitive and 1-N model for PPI
|
||||
if(i > 15)
|
||||
GIC_SetLevelModel(i, 0, 1);
|
||||
//Disable SGI and PPI interrupts
|
||||
GIC_DisableIRQ(i);
|
||||
//Set priority
|
||||
GIC_SetPriority(i, priority_field/2);
|
||||
}
|
||||
//Enable interface
|
||||
GIC_EnableInterface();
|
||||
//Set binary point to 0
|
||||
GIC_SetBinaryPoint(0);
|
||||
//Set priority mask
|
||||
GIC_InterfacePriorityMask(0xff);
|
||||
}
|
||||
|
||||
void GIC_Enable(void)
|
||||
{
|
||||
GIC_DistInit();
|
||||
GIC_CPUInterfaceInit(); //per CPU
|
||||
}
|
||||
/** GIC end **/
|
||||
@@ -0,0 +1,360 @@
|
||||
/**************************************************************************//**
|
||||
* @file gic.h
|
||||
* @brief Generic Interrupt Controller (GIC) functions
|
||||
* @version
|
||||
* @date 29 August 2013
|
||||
*
|
||||
* @note
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2011 - 2013 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
*
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef GIC_H_
|
||||
#define GIC_H_
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef enum IRQn
|
||||
{
|
||||
/****** SGI Interrupts Numbers ****************************************/
|
||||
SGI0_IRQn = 0,
|
||||
SGI1_IRQn = 1,
|
||||
SGI2_IRQn = 2,
|
||||
SGI3_IRQn = 3,
|
||||
SGI4_IRQn = 4,
|
||||
SGI5_IRQn = 5,
|
||||
SGI6_IRQn = 6,
|
||||
SGI7_IRQn = 7,
|
||||
SGI8_IRQn = 8,
|
||||
SGI9_IRQn = 9,
|
||||
SGI10_IRQn = 10,
|
||||
SGI11_IRQn = 11,
|
||||
SGI12_IRQn = 12,
|
||||
SGI13_IRQn = 13,
|
||||
SGI14_IRQn = 14,
|
||||
SGI15_IRQn = 15,
|
||||
|
||||
/****** Cortex-R4 Processor Exceptions Numbers ****************************************/
|
||||
PrivTimer_IRQn = 34, /*!< Private Timer Interrupt */
|
||||
|
||||
/****** Platform Exceptions Numbers ***************************************************/
|
||||
Watchdog_IRQn = 32, /*!< SP805 Interrupt */
|
||||
Timer0_IRQn = 34, /*!< SP804 Interrupt */
|
||||
Timer1_IRQn = 35, /*!< SP804 Interrupt */
|
||||
RTClock_IRQn = 36, /*!< PL031 Interrupt */
|
||||
UART0_IRQn = 37, /*!< PL011 Interrupt */
|
||||
UART1_IRQn = 38, /*!< PL011 Interrupt */
|
||||
UART2_IRQn = 39, /*!< PL011 Interrupt */
|
||||
UART3_IRQn = 40, /*!< PL011 Interrupt */
|
||||
MCI0_IRQn = 41, /*!< PL180 Interrupt (1st) */
|
||||
MCI1_IRQn = 42, /*!< PL180 Interrupt (2nd) */
|
||||
AACI_IRQn = 43, /*!< PL041 Interrupt */
|
||||
Keyboard_IRQn = 44, /*!< PL050 Interrupt */
|
||||
Mouse_IRQn = 45, /*!< PL050 Interrupt */
|
||||
CLCD_IRQn = 46, /*!< PL111 Interrupt */
|
||||
Ethernet_IRQn = 47, /*!< SMSC_91C111 Interrupt */
|
||||
VFS2_IRQn = 73, /*!< VFS2 Interrupt */
|
||||
} IRQn_Type;
|
||||
|
||||
/* IO definitions (access restrictions to peripheral registers) */
|
||||
/**
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define __I volatile /*!< Defines 'read only' permissions */
|
||||
#else
|
||||
#define __I volatile const /*!< Defines 'read only' permissions */
|
||||
#endif
|
||||
#define __O volatile /*!< Defines 'write only' permissions */
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
/** \brief Structure type to access the Generic Interrupt Controller Distributor (GICD)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ICDDCR;
|
||||
__I uint32_t ICDICTR;
|
||||
__I uint32_t ICDIIDR;
|
||||
uint32_t RESERVED0[29];
|
||||
__IO uint32_t ICDISR[32];
|
||||
__IO uint32_t ICDISER[32];
|
||||
__IO uint32_t ICDICER[32];
|
||||
__IO uint32_t ICDISPR[32];
|
||||
__IO uint32_t ICDICPR[32];
|
||||
__I uint32_t ICDABR[32];
|
||||
uint32_t RESERVED1[32];
|
||||
__IO uint32_t ICDIPR[256];
|
||||
__IO uint32_t ICDIPTR[256];
|
||||
__IO uint32_t ICDICFR[64];
|
||||
uint32_t RESERVED2[128];
|
||||
__IO uint32_t ICDSGIR;
|
||||
} GICDistributor_Type;
|
||||
|
||||
/** \brief Structure type to access the Controller Interface (GICC)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t ICCICR; // +0x000 - RW - CPU Interface Control Register
|
||||
__IO uint32_t ICCPMR; // +0x004 - RW - Interrupt Priority Mask Register
|
||||
__IO uint32_t ICCBPR; // +0x008 - RW - Binary Point Register
|
||||
__I uint32_t ICCIAR; // +0x00C - RO - Interrupt Acknowledge Register
|
||||
__IO uint32_t ICCEOIR; // +0x010 - WO - End of Interrupt Register
|
||||
__I uint32_t ICCRPR; // +0x014 - RO - Running Priority Register
|
||||
__I uint32_t ICCHPIR; // +0x018 - RO - Highest Pending Interrupt Register
|
||||
__IO uint32_t ICCABPR; // +0x01C - RW - Aliased Binary Point Register
|
||||
|
||||
uint32_t RESERVED[55];
|
||||
|
||||
__I uint32_t ICCIIDR; // +0x0FC - RO - CPU Interface Identification Register
|
||||
} GICInterface_Type;
|
||||
|
||||
/*@} end of GICD */
|
||||
|
||||
/* ########################## GIC functions #################################### */
|
||||
/** \brief Functions that manage interrupts via the GIC.
|
||||
@{
|
||||
*/
|
||||
|
||||
/** \brief Enable DistributorGICInterface->ICCICR |= 1; //enable interface
|
||||
|
||||
Enables the forwarding of pending interrupts to the CPU interfaces.
|
||||
|
||||
*/
|
||||
void GIC_EnableDistributor(void);
|
||||
|
||||
/** \brief Disable Distributor
|
||||
|
||||
Disables the forwarding of pending interrupts to the CPU interfaces.
|
||||
|
||||
*/
|
||||
void GIC_DisableDistributor(void);
|
||||
|
||||
/** \brief Provides information about the configuration of the GIC.
|
||||
Provides information about the configuration of the GIC.
|
||||
- whether the GIC implements the Security Extensions
|
||||
- the maximum number of interrupt IDs that the GIC supports
|
||||
- the number of CPU interfaces implemented
|
||||
- if the GIC implements the Security Extensions, the maximum number of implemented Lockable Shared Peripheral Interrupts (LSPIs).
|
||||
|
||||
\return Distributor Information.
|
||||
*/
|
||||
uint32_t GIC_DistributorInfo(void);
|
||||
|
||||
/** \brief Distributor Implementer Identification Register.
|
||||
|
||||
Distributor Implementer Identification Register
|
||||
|
||||
\return Implementer Information.
|
||||
*/
|
||||
uint32_t GIC_DistributorImplementer(void);
|
||||
|
||||
/** \brief Set list of processors that the interrupt is sent to if it is asserted.
|
||||
|
||||
The ICDIPTRs provide an 8-bit CPU targets field for each interrupt supported by the GIC.
|
||||
This field stores the list of processors that the interrupt is sent to if it is asserted.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] target CPU target
|
||||
*/
|
||||
void GIC_SetTarget(IRQn_Type IRQn, uint32_t cpu_target);
|
||||
|
||||
/** \brief Get list of processors that the interrupt is sent to if it is asserted.
|
||||
|
||||
The ICDIPTRs provide an 8-bit CPU targets field for each interrupt supported by the GIC.
|
||||
This field stores the list of processors that the interrupt is sent to if it is asserted.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] target CPU target
|
||||
*/
|
||||
uint32_t GIC_GetTarget(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Enable Interface
|
||||
|
||||
Enables the signalling of interrupts to the target processors.
|
||||
|
||||
*/
|
||||
void GIC_EnableInterface(void);
|
||||
|
||||
/** \brief Disable Interface
|
||||
|
||||
Disables the signalling of interrupts to the target processors.
|
||||
|
||||
*/
|
||||
void GIC_DisableInterface(void);
|
||||
|
||||
/** \brief Acknowledge Interrupt
|
||||
|
||||
The function acknowledges the highest priority pending interrupt and returns its IRQ number.
|
||||
|
||||
\return Interrupt number
|
||||
*/
|
||||
IRQn_Type GIC_AcknowledgePending(void);
|
||||
|
||||
/** \brief End Interrupt
|
||||
|
||||
The function writes the end of interrupt register, indicating that handling of the interrupt is complete.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
*/
|
||||
void GIC_EndInterrupt(IRQn_Type IRQn);
|
||||
|
||||
|
||||
/** \brief Enable Interrupt
|
||||
|
||||
Set-enable bit for each interrupt supported by the GIC.
|
||||
|
||||
\param [in] IRQn External interrupt number.
|
||||
*/
|
||||
void GIC_EnableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Disable Interrupt
|
||||
|
||||
Clear-enable bit for each interrupt supported by the GIC.
|
||||
|
||||
\param [in] IRQn Number of the external interrupt to disable
|
||||
*/
|
||||
void GIC_DisableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Set Pending Interrupt
|
||||
|
||||
Set-pending bit for each interrupt supported by the GIC.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
*/
|
||||
void GIC_SetPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Clear Pending Interrupt
|
||||
|
||||
Clear-pending bit for each interrupt supported by the GIC
|
||||
|
||||
\param [in] IRQn Number of the interrupt for clear pending
|
||||
*/
|
||||
void GIC_ClearPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Int_config field for each interrupt supported by the GIC.
|
||||
|
||||
This field identifies whether the corresponding interrupt is:
|
||||
(1) edge-triggered or (0) level-sensitive
|
||||
(1) 1-N model or (0) N-N model
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] edge_level (1) edge-triggered or (0) level-sensitive
|
||||
\param [in] model (1) 1-N model or (0) N-N model
|
||||
*/
|
||||
void GIC_SetLevelModel(IRQn_Type IRQn, int8_t edge_level, int8_t model);
|
||||
|
||||
|
||||
/** \brief Set Interrupt Priority
|
||||
|
||||
The function sets the priority of an interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\param [in] priority Priority to set.
|
||||
*/
|
||||
void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority);
|
||||
|
||||
/** \brief Get Interrupt Priority
|
||||
|
||||
The function reads the priority of an interrupt.
|
||||
|
||||
\param [in] IRQn Interrupt number.
|
||||
\return Interrupt Priority.
|
||||
*/
|
||||
uint32_t GIC_GetPriority(IRQn_Type IRQn);
|
||||
|
||||
/** \brief CPU Interface Priority Mask Register
|
||||
|
||||
The priority mask level for the CPU interface. If the priority of an interrupt is higher than the
|
||||
value indicated by this field, the interface signals the interrupt to the processor.
|
||||
|
||||
\param [in] Mask.
|
||||
*/
|
||||
void GIC_InterfacePriorityMask(uint32_t priority);
|
||||
|
||||
/** \brief Set the binary point.
|
||||
|
||||
Set the point at which the priority value fields split into two parts, the group priority field and the subpriority field.
|
||||
|
||||
\param [in] Mask.
|
||||
*/
|
||||
void GIC_SetBinaryPoint(uint32_t binary_point);
|
||||
|
||||
/** \brief Get the binary point.
|
||||
|
||||
Get the point at which the priority value fields split into two parts, the group priority field and the subpriority field.
|
||||
|
||||
\return Binary point.
|
||||
*/
|
||||
uint32_t GIC_GetBinaryPoint(uint32_t binary_point);
|
||||
|
||||
/** \brief Get Interrupt state.
|
||||
|
||||
Get the interrupt state, whether pending and/or active
|
||||
|
||||
\return 0 - inactive, 1 - pending, 2 - active, 3 - pending and active
|
||||
*/
|
||||
uint32_t GIC_GetIRQStatus(IRQn_Type IRQn);
|
||||
|
||||
/** \brief Send Software Generated interrupt
|
||||
|
||||
Provides an interrupt priority filter. Only interrupts with higher priority than the value in this register can be signalled to the processor.
|
||||
GIC_InterfacePriorityMask
|
||||
\param [in] IRQn The Interrupt ID of the SGI.
|
||||
\param [in] target_list CPUTargetList
|
||||
\param [in] filter_list TargetListFilter
|
||||
*/
|
||||
void GIC_SendSGI(IRQn_Type IRQn, uint32_t target_list, uint32_t filter_list);
|
||||
|
||||
/** \brief API call to initialise the interrupt distributor
|
||||
|
||||
API call to initialise the interrupt distributor
|
||||
|
||||
*/
|
||||
void GIC_DistInit(void);
|
||||
|
||||
/** \brief API call to initialise the CPU interface
|
||||
|
||||
API call to initialise the CPU interface
|
||||
|
||||
*/
|
||||
void GIC_CPUInterfaceInit(void);
|
||||
|
||||
/** \brief API call to set the Interrupt Configuration Registers
|
||||
|
||||
API call to initialise the Interrupt Configuration Registers
|
||||
|
||||
*/
|
||||
void GIC_SetICDICFR (const uint32_t *ICDICFRn);
|
||||
|
||||
/** \brief API call to Enable the GIC
|
||||
|
||||
API call to Enable the GIC
|
||||
|
||||
*/
|
||||
void GIC_Enable(void);
|
||||
|
||||
#endif /* GIC_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
;**************************************************
|
||||
; Copyright (c) 2017 ARM Ltd. All rights reserved.
|
||||
;**************************************************
|
||||
|
||||
; Scatter-file for RTX Example on Versatile Express R4
|
||||
|
||||
; This scatter-file places application code, data and peripherals at suitable addresses in the memory map.
|
||||
|
||||
; This platform has 2GB SDRAM starting at 0x0.
|
||||
|
||||
|
||||
SDRAM 0x0 0x40000000
|
||||
{
|
||||
CODE +0 0x200000
|
||||
{
|
||||
startup.o (Vectors, +FIRST) ; Vector table and other (assembler) startup code
|
||||
* (InRoot$$Sections) ; All (library) code that must be in a root region
|
||||
* (+RO-CODE) ; Application RO code (.text)
|
||||
* (+RO-DATA) ; Application RO data (.constdata)
|
||||
}
|
||||
|
||||
IRQ_STACK +0 ALIGN 8 EMPTY 1024 {}
|
||||
|
||||
FIQ_STACK +0 ALIGN 8 EMPTY 512 {}
|
||||
|
||||
SVC_STACK +0 ALIGN 8 EMPTY 2048 {}
|
||||
|
||||
SYS_STACK +0 ALIGN 8 EMPTY 2048 {}
|
||||
|
||||
ABORT_STACK +0 ALIGN 8 EMPTY 2048 {}
|
||||
|
||||
; Application RW & ZI data (.data & .bss)
|
||||
DATA +0 0x100000
|
||||
{
|
||||
* (+RW,+ZI)
|
||||
}
|
||||
|
||||
PERIPHERALS 0xA0000000 EMPTY 0x20000000 { }; Peripherals
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/* Small demonstration of the ThreadX module manager. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD module_manager;
|
||||
TXM_MODULE_INSTANCE my_module;
|
||||
|
||||
UCHAR manager_stack[1024];
|
||||
|
||||
/* Define the object pool area. */
|
||||
|
||||
UCHAR object_memory[16384];
|
||||
|
||||
/* Define the module data pool area. */
|
||||
#define MODULE_DATA_SIZE 65536
|
||||
unsigned char module_data_area[MODULE_DATA_SIZE];
|
||||
|
||||
/* Module code is in an array created by module_to_c_array utility. */
|
||||
extern const unsigned char module_code[];
|
||||
|
||||
/* Define the count of memory faults. */
|
||||
|
||||
ULONG memory_faults;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void module_manager_entry(ULONG thread_input);
|
||||
|
||||
|
||||
/* Define fault handler. */
|
||||
|
||||
VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module)
|
||||
{
|
||||
|
||||
/* Just increment the fault counter. */
|
||||
memory_faults++;
|
||||
}
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
/* Setup the timer. */
|
||||
timer_init();
|
||||
|
||||
/* Enter the ThreadX kernel. */
|
||||
tx_kernel_enter();
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
tx_thread_create(&module_manager, "Module Manager Thread", module_manager_entry, 0,
|
||||
manager_stack, DEMO_STACK_SIZE,
|
||||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the test threads. */
|
||||
|
||||
void module_manager_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
/* Initialize the module manager. */
|
||||
txm_module_manager_initialize((VOID *) module_data_area, MODULE_DATA_SIZE);
|
||||
|
||||
txm_module_manager_object_pool_create(object_memory, sizeof(object_memory));
|
||||
|
||||
/* Register a fault handler. */
|
||||
txm_module_manager_memory_fault_notify(module_fault_handler);
|
||||
|
||||
/* Load the module that is already there, in this example it is placed there by the multiple image download. */
|
||||
txm_module_manager_in_place_load(&my_module, "my module", (VOID *) 0x00100000 /*module_code*/);
|
||||
|
||||
/* Enable 128 byte read/write shared memory region at 0x08025000. */
|
||||
txm_module_manager_external_memory_enable(&my_module, (void *) 0x08025000, 128, TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE);
|
||||
|
||||
/* Start the module. */
|
||||
txm_module_manager_start(&my_module);
|
||||
|
||||
/* Sleep for a while.... */
|
||||
tx_thread_sleep(300);
|
||||
|
||||
/* Stop the module. */
|
||||
txm_module_manager_stop(&my_module);
|
||||
|
||||
/* Unload the module. */
|
||||
txm_module_manager_unload(&my_module);
|
||||
|
||||
/* Load the module that is already there. */
|
||||
txm_module_manager_in_place_load(&my_module, "my module", (VOID *) 0x00100000);
|
||||
|
||||
/* Set maximum module priority to 5. */
|
||||
txm_module_manager_maximum_module_priority_set(&my_module, 5);
|
||||
/* In this demo, module threads 0 and 5 will not start because their priorities
|
||||
* are higher than 5. */
|
||||
|
||||
/* Start the module again. */
|
||||
txm_module_manager_start(&my_module);
|
||||
|
||||
/* Now just spin... */
|
||||
while(1)
|
||||
{
|
||||
|
||||
tx_thread_sleep(100);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
//----------------------------------------------------------------
|
||||
// Cortex-R4(F) Embedded example - Startup Code
|
||||
//
|
||||
// Copyright (c) 2006-2018 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
|
||||
#define FIQ_MODE 0x11
|
||||
#define IRQ_MODE 0x12
|
||||
#define SVC_MODE 0x13
|
||||
#define ABT_MODE 0x17
|
||||
#define SYS_MODE 0x1F
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.eabi_attribute Tag_ABI_align8_preserved,1
|
||||
|
||||
.section VECTORS,"ax"
|
||||
.align 3
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Exception Vector Table
|
||||
//----------------------------------------------------------------
|
||||
// Note: LDR PC instructions are used here, though branch (B) instructions
|
||||
// could also be used, unless the exception handlers are >32MB away.
|
||||
|
||||
.global Vectors
|
||||
|
||||
Vectors:
|
||||
LDR PC, Reset_Addr
|
||||
LDR pc,=__tx_undefined // Undefined handler
|
||||
LDR pc,=__tx_svc_interrupt // Software interrupt handler
|
||||
LDR pc,=__tx_prefetch_handler // Prefetch exception handler
|
||||
LDR pc,=__tx_abort_handler // Abort exception handler
|
||||
LDR pc,=__tx_reserved_handler // Reserved exception handler
|
||||
LDR pc,=__tx_irq_handler // IRQ interrupt handler
|
||||
LDR pc,=__tx_fiq_handler // FIQ interrupt handler
|
||||
|
||||
|
||||
.balign 4
|
||||
Reset_Addr: .word Reset_Handler
|
||||
Undefined_Addr: .word __tx_undefined
|
||||
SVC_Addr: .word __tx_svc_interrupt
|
||||
Prefetch_Addr: .word __tx_prefetch_handler
|
||||
Abort_Addr: .word __tx_abort_handler
|
||||
IRQ_Addr: .word __tx_irq_handler
|
||||
FIQ_Addr: .word __tx_fiq_handler
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Reset Handler
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.global Reset_Handler
|
||||
.type Reset_Handler, "function"
|
||||
Reset_Handler:
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Disable MPU and caches
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Disable MPU and cache in case it was left enabled from an earlier run
|
||||
// This does not need to be done from a cold reset
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
|
||||
BIC r0, r0, #(0x1 << 12) // Clear I bit 12 to disable I Cache
|
||||
BIC r0, r0, #(0x1 << 2) // Clear C bit 2 to disable D Cache
|
||||
BIC r0, r0, #0x1 // Clear M bit 0 to disable MPU
|
||||
DSB // Ensure all previous loads/stores have completed
|
||||
MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
|
||||
ISB // Ensure subsequent insts execute wrt new MPU settings
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Disable Branch prediction
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// In the Cortex-R4, the Z-bit of the SCTLR does not control the program flow prediction.
|
||||
// Some control bits in the ACTLR control the program flow and prefetch features instead.
|
||||
// These are enabled by default, but are shown here for completeness.
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 1 // Read ACTLR
|
||||
ORR r0, r0, #(0x1 << 17) // Enable RSDIS bit 17 to disable the return stack
|
||||
ORR r0, r0, #(0x1 << 16) // Clear BP bit 15 and set BP bit 16:
|
||||
BIC r0, r0, #(0x1 << 15) // Branch always not taken and history table updates disabled
|
||||
MCR p15, 0, r0, c1, c0, 1 // Write ACTLR
|
||||
ISB
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Cache invalidation
|
||||
//----------------------------------------------------------------
|
||||
|
||||
DSB // Complete all outstanding explicit memory operations
|
||||
|
||||
MOV r0, #0
|
||||
|
||||
MCR p15, 0, r0, c7, c5, 0 // Invalidate entire instruction cache
|
||||
MCR p15, 0, r0, c15, c5, 0 // Invalidate entire data cache
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Initialize Supervisor Mode Stack using Linker symbol from scatter file.
|
||||
// Stacks must be 8 byte aligned.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
/****** NOTE ****** We must be in SVC MODE at this point. Some monitors
|
||||
enter this routine in USER mode and require a software interrupt to
|
||||
change into SVC mode. */
|
||||
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
/* Setup the system mode stack for nested interrupt support */
|
||||
MOV r3, #SYS_MODE // Build SYS mode CPSR
|
||||
MSR CPSR_c, r3 // Enter SYS mode
|
||||
LDR sp, =Image$$SYS_STACK$$ZI$$Limit // Setup SYS stack pointer
|
||||
#endif
|
||||
|
||||
CPS #ABT_MODE // Build Abort mode CPSR
|
||||
LDR sp, =Image$$ABORT_STACK$$ZI$$Limit // Setup abort stack pointer
|
||||
|
||||
CPS #FIQ_MODE // Build FIQ mode CPSR
|
||||
LDR sp, =Image$$FIQ_STACK$$ZI$$Limit // Setup FIQ stack pointer
|
||||
MOV sl, #0 // Clear sl
|
||||
MOV fp, #0 // Clear fp
|
||||
|
||||
CPS #IRQ_MODE // Build IRQ mode CPSR
|
||||
LDR sp, =Image$$IRQ_STACK$$ZI$$Limit // Setup IRQ stack pointer
|
||||
|
||||
CPS #SVC_MODE // Build SVC mode CPSR
|
||||
LDR sp, =Image$$SVC_STACK$$ZI$$Limit // Setup SVC stack pointer
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// TCM Configuration
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Cortex-R4 optionally provides two Tightly-Coupled Memory (TCM) blocks (ATCM and BTCM) for fast access to code or data.
|
||||
// ATCM typically holds interrupt or exception code that must be accessed at high speed,
|
||||
// without any potential delay resulting from a cache miss.
|
||||
// BTCM typically holds a block of data for intensive processing, such as audio or video data.
|
||||
// In the Cortex-R4 processor, both ATCM and BTCM support both instruction and data accesses.
|
||||
|
||||
// The following illustrates basic TCM configuration, as the basis for exploration by the user
|
||||
|
||||
#ifdef TCM
|
||||
.global Image$$ATCM$$Base
|
||||
.global Image$$BTCM0$$Base
|
||||
.global Image$$BTCM1$$Base
|
||||
|
||||
MRC p15, 0, r0, c0, c0, 2 // Read TCM Type Register
|
||||
// r0 now contains ATCM & BTCM availability
|
||||
|
||||
MRC p15, 0, r0, c9, c1, 1 // Read ATCM Region Register
|
||||
// r0 now contains ATCM size in bits [6:2]
|
||||
|
||||
MRC p15, 0, r0, c9, c1, 0 // Read BTCM Region Register
|
||||
// r0 now contains BTCM size in bits [6:2]
|
||||
|
||||
// The Cortex-R4F Core Tile has
|
||||
// 64K ATCM from 0xE0FD0000 to 0xE0FDFFFF
|
||||
// 64K BTCM0 from 0xE0FE0000 to 0xE0FEFFFF
|
||||
// 64K BTCM1 from 0xE0FF0000 to 0xE0FFFFFF
|
||||
|
||||
LDR r0, =Image$$ATCM$$Base // Set ATCM base address
|
||||
ORR r0, r0, #1 // Enable it
|
||||
MCR p15, 0, r0, c9, c1, 1 // Write ATCM Region Register
|
||||
|
||||
LDR r0, =Image$$BTCM0$$Base // Set BTCM base address
|
||||
ORR r0, r0, #1 // Enable it
|
||||
MCR p15, 0, r0, c9, c1, 0 // Write BTCM Region Register
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_FP
|
||||
//----------------------------------------------------------------
|
||||
// Enable access to VFP by enabling access to Coprocessors 10 and 11.
|
||||
// Enables Full Access i.e. in both privileged and non privileged modes
|
||||
//----------------------------------------------------------------
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 2 // Read Coprocessor Access Control Register (CPACR)
|
||||
ORR r0, r0, #(0xF << 20) // Enable access to CP 10 & 11
|
||||
MCR p15, 0, r0, c1, c0, 2 // Write Coprocessor Access Control Register (CPACR)
|
||||
ISB
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Switch on the VFP hardware
|
||||
//----------------------------------------------------------------
|
||||
|
||||
MOV r0, #0x40000000
|
||||
VMSR FPEXC, r0 // Write FPEXC register, EN bit set
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Enable Branch prediction
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// In the Cortex-R4, the Z-bit of the SCTLR does not control the program flow prediction.
|
||||
// Some control bits in the ACTLR control the program flow and prefetch features instead.
|
||||
// These are enabled by default, but are shown here for completeness.
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 1 // Read ACTLR
|
||||
BIC r0, r0, #(0x1 << 17) // Clear RSDIS bit 17 to enable return stack
|
||||
BIC r0, r0, #(0x1 << 16) // Clear BP bit 15 and BP bit 16:
|
||||
BIC r0, r0, #(0x1 << 15) // Normal operation, BP is taken from the global history table.
|
||||
MCR p15, 0, r0, c1, c0, 1 // Write ACTLR
|
||||
ISB
|
||||
|
||||
|
||||
/* Enable the GIC. */
|
||||
BL GIC_Enable
|
||||
|
||||
.global __main
|
||||
B __main
|
||||
|
||||
.size Reset_Handler, . - Reset_Handler
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Global Enable for Instruction and Data Caching
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.global enable_caches
|
||||
|
||||
.type enable_caches, "function"
|
||||
.cfi_startproc
|
||||
enable_caches:
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
|
||||
ORR r0, r0, #(0x1 << 12) // enable I Cache
|
||||
ORR r0, r0, #(0x1 << 2) // enable D Cache
|
||||
MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
|
||||
ISB
|
||||
|
||||
BX lr
|
||||
.cfi_endproc
|
||||
|
||||
.size enable_caches, . - enable_caches
|
||||
|
||||
/* Define initial heap/stack routine for the ARM RealView (and ADS) startup code. This
|
||||
routine will set the initial stack to use the ThreadX IRQ & FIQ &
|
||||
(optionally SYS) stack areas. */
|
||||
|
||||
.global __user_initial_stackheap
|
||||
.type __user_initial_stackheap, %function
|
||||
__user_initial_stackheap:
|
||||
|
||||
LDR r1, =Image$$SVC_STACK$$ZI$$Limit
|
||||
BX lr // Return to caller
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "gic.h"
|
||||
|
||||
/* Systick registers */
|
||||
#define PRIVTIM_IRQ 34
|
||||
#define PRIVATE_TIMER_BASE (0xB0110000)
|
||||
#define PRIVTIM_RELOAD (*((volatile uint32_t *)(PRIVATE_TIMER_BASE + 0x0)))
|
||||
#define PRIVTIM_CURRENT (*((volatile uint32_t *)(PRIVATE_TIMER_BASE + 0x4)))
|
||||
#define PRIVTIM_CTRL (*((volatile uint32_t *)(PRIVATE_TIMER_BASE + 0x8)))
|
||||
#define PRIVTIM_STATUS (*((volatile uint32_t *)(PRIVATE_TIMER_BASE + 0xc)))
|
||||
|
||||
#define OS_CLOCK 12000000
|
||||
#define OS_TICK 1000
|
||||
#define OS_TRV ((uint32_t)(((double)OS_CLOCK*(double)OS_TICK)/1E6)-1)
|
||||
|
||||
#define U32 uint32_t
|
||||
#define GICD_ICDICER0 (*((volatile U32 *)(GICDistributor_BASE + 0x180))) /* - RW - Interrupt Clear-Enable Registers */
|
||||
#define GICD_ICDISER0 (*((volatile U32 *)(GICDistributor_BASE + 0x100))) /* - RW - Interrupt Set-Enable Registers */
|
||||
#define GICD_ICDIPR0 (*((volatile U32 *)(GICDistributor_BASE + 0x400))) /* - RW - Interrupt Priority Registers */
|
||||
#define GICD_ICDSGIR (*((volatile U32 *)(GICDistributor_BASE + 0xf00))) /* - RW - Interrupt Software Interrupt Register */
|
||||
#define GICD_ICDICERx(irq) *(volatile U32 *)(&GICD_ICDICER0 + irq/32)
|
||||
#define GICD_ICDISERx(irq) *(volatile U32 *)(&GICD_ICDISER0 + irq/32)
|
||||
|
||||
void timer_init()
|
||||
{
|
||||
GIC_EnableIRQ(34);
|
||||
PRIVTIM_RELOAD = 0x200;
|
||||
PRIVTIM_CTRL |= 0xC0; /* Enable timer, periodic mode */
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
void timer_init();
|
||||
#endif
|
||||
@@ -0,0 +1,477 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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"
|
||||
*/
|
||||
|
||||
#define THUMB_MASK 0x20 // Thumb bit (5) of CPSR/SPSR
|
||||
#define ABT_MODE 0x17 // ABT mode
|
||||
#define SYS_MODE 0x1F // SYS mode
|
||||
|
||||
#define GICI_BASE 0xAE000000
|
||||
#define ICCIAR_OFFSET 0x0000000C
|
||||
#define ICCEOIR_OFFSET 0x00000010
|
||||
|
||||
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global _tx_thread_context_save
|
||||
.global _tx_thread_context_restore
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
.global _tx_thread_fiq_context_save
|
||||
.global _tx_thread_fiq_context_restore
|
||||
#endif
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
.global _tx_thread_irq_nesting_start
|
||||
.global _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
#ifdef TX_ENABLE_FIQ_NESTING
|
||||
.global _tx_thread_fiq_nesting_start
|
||||
.global _tx_thread_fiq_nesting_end
|
||||
#endif
|
||||
.global _tx_timer_interrupt
|
||||
.global __main
|
||||
.global _tx_version_id
|
||||
.global _tx_build_options
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Cortex-R4/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_initialize_low_level(VOID)
|
||||
{ */
|
||||
.global _tx_initialize_low_level
|
||||
.type _tx_initialize_low_level, "function"
|
||||
_tx_initialize_low_level:
|
||||
|
||||
/* Save the system stack pointer. */
|
||||
/* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */
|
||||
|
||||
LDR r0, =Image$$SVC_STACK$$ZI$$Limit
|
||||
LDR r1, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr
|
||||
STR r0, [r1] // Pickup system stack
|
||||
|
||||
/* Save the first available memory address. */
|
||||
/* _tx_initialize_unused_memory = (VOID_PTR) Image$$ZI$$Limit + HEAP + [SYS_STACK] + FIQ_STACK + IRQ_STACK; */
|
||||
|
||||
LDR r0, =Image$$DATA$$ZI$$Limit
|
||||
LDR r2, =_tx_initialize_unused_memory // Pickup unused memory ptr address
|
||||
STR r0, [r2, #0] // Save first free memory address
|
||||
|
||||
/* Return to caller. */
|
||||
BX lr // Return to caller
|
||||
/* } */
|
||||
|
||||
/* Define shells for each of the interrupt vectors. */
|
||||
|
||||
.global __tx_undefined
|
||||
.type __tx_undefined, "function"
|
||||
__tx_undefined:
|
||||
B __tx_undefined // Undefined handler
|
||||
|
||||
/*** Prefetch and abort handlers are used below for MPU fault handling
|
||||
.global __tx_prefetch_handler
|
||||
.type __tx_prefetch_handler, "function"
|
||||
__tx_prefetch_handler:
|
||||
B __tx_prefetch_handler // Prefetch exception handler
|
||||
|
||||
.global __tx_abort_handler
|
||||
.type __tx_abort_handler, "function"
|
||||
__tx_abort_handler:
|
||||
B __tx_abort_handler // Abort exception handler
|
||||
*/
|
||||
|
||||
.global __tx_reserved_handler
|
||||
.type __tx_reserved_handler, "function"
|
||||
__tx_reserved_handler:
|
||||
B __tx_reserved_handler // Reserved exception handler
|
||||
|
||||
|
||||
.global __tx_irq_handler
|
||||
.type __tx_irq_handler, "function"
|
||||
.global __tx_irq_processing_return
|
||||
.type __tx_irq_processing_return, "function"
|
||||
__tx_irq_handler:
|
||||
|
||||
/* Jump to context save to save system context. */
|
||||
B _tx_thread_context_save
|
||||
__tx_irq_processing_return:
|
||||
|
||||
/* Acknowledge the interrupt. */
|
||||
LDR r1, =GICI_BASE // Load the base of the GIC
|
||||
LDR r0, [r1, #ICCIAR_OFFSET] // Read ICCIAR (GIC CPU Interface register)
|
||||
DSB // Ensure that interrupt acknowledge completes before re-enabling interrupts
|
||||
PUSH {r0, r1} // Save the IRQ ID and the GIC base address on the stack
|
||||
|
||||
/* Clear the timer interrupt. */
|
||||
LDR r0, =0xB0110000 // Load the base address of the timer
|
||||
MOV r1, #1 // Setup value to write to the interrupt clear register - can be anything.
|
||||
STR r1, [r0, #0x0C] // Clear the interrupt. 0x0C is the offset to the interrupt clear register.
|
||||
|
||||
/* At this point execution is still in the IRQ mode. The CPSR, point of
|
||||
interrupt, and all C scratch registers are available for use. In
|
||||
addition, IRQ interrupts may be re-enabled - with certain restrictions -
|
||||
if nested IRQ interrupts are desired. Interrupts may be re-enabled over
|
||||
small code sequences where lr is saved before enabling interrupts and
|
||||
restored after interrupts are again disabled. */
|
||||
|
||||
|
||||
BL _tx_timer_interrupt // Timer interrupt handler
|
||||
_tx_not_timer_interrupt:
|
||||
|
||||
/* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
|
||||
from IRQ mode with interrupts disabled. This routine switches to the
|
||||
system mode and returns with IRQ interrupts enabled. */
|
||||
|
||||
/* NOTE: It is very important to ensure all IRQ interrupts are cleared
|
||||
prior to enabling nested IRQ interrupts. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_start
|
||||
#endif
|
||||
|
||||
|
||||
/* Application IRQ handlers can be called here! */
|
||||
|
||||
/* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
service must be called before returning to _tx_thread_context_restore.
|
||||
This routine returns in processing in IRQ mode with interrupts disabled. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
|
||||
POP {r0, r1} // Restore the IRQ ID and GIC base address
|
||||
STR r0, [r1, #ICCEOIR_OFFSET] // Write the IRQ ID to the End Of Interrupt register to clear the active bit
|
||||
|
||||
/* Jump to context restore to restore system context. */
|
||||
B _tx_thread_context_restore
|
||||
|
||||
|
||||
/* This is an example of a vectored IRQ handler. */
|
||||
|
||||
.global __tx_example_vectored_irq_handler
|
||||
.type __tx_example_vectored_irq_handler, "function"
|
||||
__tx_example_vectored_irq_handler:
|
||||
|
||||
|
||||
/* Save initial context and call context save to prepare for
|
||||
vectored ISR execution. */
|
||||
|
||||
/*
|
||||
STMDB sp!, {r0-r3} // Save some scratch registers
|
||||
MRS r0, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} // Store other scratch registers
|
||||
BL _tx_thread_vectored_context_save // Vectored context save
|
||||
*/
|
||||
|
||||
/* At this point execution is still in the IRQ mode. The CPSR, point of
|
||||
interrupt, and all C scratch registers are available for use. In
|
||||
addition, IRQ interrupts may be re-enabled - with certain restrictions -
|
||||
if nested IRQ interrupts are desired. Interrupts may be re-enabled over
|
||||
small code sequences where lr is saved before enabling interrupts and
|
||||
restored after interrupts are again disabled. */
|
||||
|
||||
|
||||
/* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
|
||||
from IRQ mode with interrupts disabled. This routine switches to the
|
||||
system mode and returns with IRQ interrupts enabled. */
|
||||
|
||||
/* NOTE: It is very important to ensure all IRQ interrupts are cleared
|
||||
prior to enabling nested IRQ interrupts. */
|
||||
/*
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_start
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Application IRQ handlers can be called here! */
|
||||
|
||||
/* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
service must be called before returning to _tx_thread_context_restore.
|
||||
This routine returns in processing in IRQ mode with interrupts disabled. */
|
||||
/*
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* Jump to context restore to restore system context. */
|
||||
/*
|
||||
B _tx_thread_context_restore
|
||||
*/
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
.global __tx_fiq_handler
|
||||
.type __tx_fiq_handler, "function"
|
||||
__tx_fiq_handler:
|
||||
|
||||
/* Jump to fiq context save to save system context. */
|
||||
B _tx_thread_fiq_context_save
|
||||
|
||||
.global __tx_fiq_processing_return
|
||||
.type __tx_fiq_processing_return, "function"
|
||||
__tx_fiq_processing_return:
|
||||
|
||||
/* At this point execution is still in the FIQ mode. The CPSR, point of
|
||||
interrupt, and all C scratch registers are available for use. */
|
||||
|
||||
/* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start
|
||||
from FIQ mode with interrupts disabled. This routine switches to the
|
||||
system mode and returns with FIQ interrupts enabled. */
|
||||
|
||||
/* NOTE: It is very important to ensure all FIQ interrupts are cleared
|
||||
prior to enabling nested FIQ interrupts. */
|
||||
#ifdef TX_ENABLE_FIQ_NESTING
|
||||
BL _tx_thread_fiq_nesting_start
|
||||
#endif
|
||||
|
||||
/* Application FIQ handlers can be called here! */
|
||||
|
||||
/* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
service must be called before returning to _tx_thread_fiq_context_restore. */
|
||||
#ifdef TX_ENABLE_FIQ_NESTING
|
||||
BL _tx_thread_fiq_nesting_end
|
||||
#endif
|
||||
|
||||
/* Jump to fiq context restore to restore system context. */
|
||||
B _tx_thread_fiq_context_restore
|
||||
|
||||
|
||||
#else
|
||||
.global __tx_fiq_handler
|
||||
.type __tx_fiq_handler, "function"
|
||||
__tx_fiq_handler:
|
||||
B __tx_fiq_handler // FIQ interrupt handler
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* __tx_prefetch_handler & __tx_abort_handler Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function handles MPU exceptions and fills the */
|
||||
/* _txm_module_manager_memory_fault_info struct. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_memory_fault_handler */
|
||||
/* _tx_execution_thread_exit */
|
||||
/* _tx_thread_schedule */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* MMU exceptions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
/********************************************************************
|
||||
MMU Exception Handling
|
||||
********************************************************************/
|
||||
.global _tx_thread_system_state
|
||||
.global _txm_module_manager_memory_fault_info
|
||||
.global _tx_thread_current_ptr
|
||||
.global _txm_module_manager_memory_fault_handler
|
||||
.global _tx_thread_schedule
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_thread_exit
|
||||
#endif
|
||||
|
||||
|
||||
.arm /* Exception handler in ARM mode. */
|
||||
.align 3
|
||||
.global __tx_prefetch_handler
|
||||
.global __tx_abort_handler
|
||||
.type __tx_prefetch_handler, "function"
|
||||
.type __tx_abort_handler, "function"
|
||||
|
||||
__tx_prefetch_handler:
|
||||
__tx_abort_handler:
|
||||
STMDB sp!, {r0-r3} // Save some working registers
|
||||
LDR r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3, #0] // Pickup system state
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3, #0] // Store it back in the variable
|
||||
|
||||
// Now pickup and store all the fault related information
|
||||
|
||||
// Pickup the memory fault info struct
|
||||
LDR r3, =_txm_module_manager_memory_fault_info
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup the current thread pointer
|
||||
STR r1, [r3, #0] // Save current thread pointer
|
||||
|
||||
MRC p15, 0, r0, c6, c0, 0 // Read DFAR
|
||||
STR r0, [r3, #8] // Save DFAR
|
||||
|
||||
CMP r0, #0 // Was it a data or instruction fault?
|
||||
SUBEQ lr, lr, #4 // Adjust point of exception for instruction
|
||||
SUBNE lr, lr, #8 // Adjust point of exception for data
|
||||
STR lr, [r3, #4] // Save point of fault
|
||||
|
||||
MRC p15, 0, r0, c5, c0, 0 // Read DFSR
|
||||
STR r0, [r3, #12] // Save DFSR
|
||||
MRC p15, 0, r0, c6, c0, 2 // Read IFAR
|
||||
STR r0, [r3, #16] // Save IFAR
|
||||
MRC p15, 0, r0, c5, c0, 1 // Read IFSR
|
||||
STR r0, [r3, #20] // Save IFSR
|
||||
MOV r0, #0 // Build zero register
|
||||
MCR p15, 0, r0, c6, c0, 0 // Clear DFAR
|
||||
MCR p15, 0, r0, c5, c0, 0 // Clear DFSR
|
||||
MCR p15, 0, r0, c6, c0, 2 // Clear IFAR
|
||||
MCR p15, 0, r0, c5, c0, 1 // Clear IFSR
|
||||
|
||||
// Save registers r0-r12
|
||||
POP {r0-r2}
|
||||
STR r0, [r3, #28] // Save r0
|
||||
STR r1, [r3, #32] // Save r1
|
||||
STR r2, [r3, #36] // Save r2
|
||||
POP {r0}
|
||||
STR r0, [r3, #40] // Save r3
|
||||
STR r4, [r3, #44] // Save r4
|
||||
STR r5, [r3, #48] // Save r5
|
||||
STR r6, [r3, #52] // Save r6
|
||||
STR r7, [r3, #56] // Save r7
|
||||
STR r8, [r3, #60] // Save r8
|
||||
STR r9, [r3, #64] // Save r9
|
||||
STR r10,[r3, #68] // Save r10
|
||||
STR r11,[r3, #72] // Save r11
|
||||
STR r12,[r3, #76] // Save r12
|
||||
|
||||
CPS #SYS_MODE // Enter SYS mode
|
||||
MOV r0, lr // Pickup lr
|
||||
MOV r1, sp // Pickup sp
|
||||
CPS #ABT_MODE // Back to ABT mode
|
||||
STR r0, [r3, #80] // Save lr
|
||||
STR r1, [r3, #24] // Save sp
|
||||
MRS r0, SPSR // Pickup SPSR
|
||||
STR r0, [r3, #84] // Save SPSR
|
||||
ORR r0, r0, #SYS_MODE // Return into SYS mode
|
||||
BIC r0, r0, #THUMB_MASK // Clear THUMB mode
|
||||
MSR SPSR_c, r0 // Save SPSR
|
||||
|
||||
// Call memory manager fault handler
|
||||
BL _txm_module_manager_memory_fault_handler
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
#endif
|
||||
|
||||
LDR r0, =_tx_thread_system_state // Pickup address of system state
|
||||
LDR r1, [r0] // Pickup system state
|
||||
SUB r1, r1, #1 // Decrement
|
||||
STR r1, [r0] // Store new system state
|
||||
|
||||
MOV r1, #0 // Build NULL value
|
||||
LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer
|
||||
STR r1, [r0] // Clear current thread pointer
|
||||
|
||||
// Return from exception
|
||||
LDR lr, =_tx_thread_schedule // Load scheduler address
|
||||
SUBS pc, lr, #0 // Return to scheduler
|
||||
/********************************************************************
|
||||
End of MMU exception handling.
|
||||
********************************************************************/
|
||||
|
||||
/* Reference build options and version ID to ensure they come in. */
|
||||
|
||||
LDR r2, =_tx_build_options // Pickup build options variable address
|
||||
LDR r0, [r2, #0] // Pickup build options content
|
||||
LDR r2, =_tx_version_id // Pickup version ID variable address
|
||||
LDR r0, [r2, #0] // Pickup version ID content
|
||||
File diff suppressed because one or more lines are too long
140
ports_module/cortex_r4/ac6/example_build/tx/.cproject
Normal file
140
ports_module/cortex_r4/ac6/example_build/tx/.cproject
Normal file
@@ -0,0 +1,140 @@
|
||||
<?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.397785280">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.397785280" 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="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.397785280" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.397785280." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.debug.1873800485" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.debug">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.toolchain.v6.base.options.debug.level.291608604" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.524053182" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R4.VFPv3_D16" valueType="string"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.floatabi.379461077" name="Float ABI" superClass="com.arm.toolchain.v6.base.options.floatabi" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.inst.1534434276" name="Instruction set" superClass="com.arm.toolchain.v6.base.options.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.debug.397785280..2133581333" name=""/>
|
||||
<builder buildPath="${workspace_loc:/cortex-r4}/Debug" id="com.arm.toolchain.v6.builder.158492155" 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.1297960997" 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.706686674" 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.331758084" 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.cpu.1198921237" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.target.1574004324" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.fpu.792842113" name="FPU (-mfpu)" superClass="com.arm.tool.c.compiler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.floatabi.480356500" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.c.compiler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.inst.232951986" name="Instruction set" superClass="com.arm.tool.c.compiler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.defmac.977735094" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.preproconly.426601175" name="Preprocess only (-E)" superClass="com.arm.tool.c.compiler.v6.base.option.preproconly" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings.148885147" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.incpath.679205895" 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_generic_module_manager}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_generic_modules}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/>
|
||||
</option>
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.712152796" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.1604102559" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.1037714875" 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.1630996211" 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.1682803592" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.924011715" 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.2069795992" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.1693345089" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.target.1633066570" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" useByScannerDiscovery="false" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.fpu.36352317" name="FPU (-mfpu)" superClass="com.arm.tool.assembler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.floatabi.1661460616" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.assembler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.inst.1927837470" name="Instruction set" superClass="com.arm.tool.assembler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.defmac.1739378921" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac" useByScannerDiscovery="false"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.options.target.enableToolSpecificSettings.1670740136" name="Enable tool specific settings" superClass="com.arm.tool.assembler.v6.base.options.target.enableToolSpecificSettings" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.flags.179733834" name="Other flags" superClass="com.arm.tool.assembler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="-DTX_THUMB_MODE"/>
|
||||
</option>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.796990181" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.1524994417" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6">
|
||||
<option id="com.arm.tool.c.linker.option.entry.1136793463" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" useByScannerDiscovery="false" value="Start" valueType="string"/>
|
||||
<option id="com.arm.tool.c.linker.option.scatter.1332412624" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" useByScannerDiscovery="false" value="../sample_threadx.scat" valueType="string"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.librarian.v6.799407983" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="txm_module_manager_in_place_load_original.c|txm_module_manager_in_place_load_unmodified.c|txm_module_manager_in_place_load_modified.c|txm_module_manager_mm_register_setup_new.c|txm_module_manager_internal_load_unmodified.c|txm_module_manager_in_place_load_new.c|tx_initialize_low_level_before_merging_with_startup.S|backups" 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.exe.release.524725615">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.release.524725615" 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="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.release.524725615" name="Release" parent="com.arm.eclipse.build.config.v6.exe.release">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.release.524725615." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.exe.release.1762944403" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.exe.release">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.toolchain.v6.base.options.debug.level.1087046132" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.exe.release.524725615..145961642" name=""/>
|
||||
<builder buildPath="${workspace_loc:/cortex-r4}/Release" id="com.arm.toolchain.v6.builder.559511441" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/>
|
||||
<tool id="com.arm.tool.c.compiler.v6.131184611" 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.488740147" 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.1314985600" 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.820494980" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.771667771" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.1218809671" 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.1008193656" 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.1610243813" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.348130542" 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.1819445556" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.699090690" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.595616399" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6"/>
|
||||
<tool id="com.arm.tool.librarian.v6.484994551" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="backups|tx_thread_fiq_context_restore.S|tx_thread_context_save.S|tx_thread_context_restore.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="cortex-a9.com.arm.eclipse.build.project.baremetal.exe.827478944" name="Executable" projectType="com.arm.eclipse.build.project.baremetal.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="/tx"/>
|
||||
</configuration>
|
||||
<configuration configurationName="Release">
|
||||
<resource resourceType="PROJECT" workspacePath="/cortex-r4"/>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="com.arm.projectSettings" version="5.25"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
</cproject>
|
||||
63
ports_module/cortex_r4/ac6/example_build/tx/.project
Normal file
63
ports_module/cortex_r4/ac6/example_build/tx/.project
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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_generic_module_manager</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common_modules/module_manager/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>inc_generic_modules</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common_modules/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_generic_module_manager</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common_modules/module_manager/src</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/module_manager/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="com.arm.eclipse.build.config.v6.exe.debug.397785280" 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="1285801792837881262" 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.524725615" 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="1208898303067000398" 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>
|
||||
152
ports_module/cortex_r4/ac6/example_build/txm/.cproject
Normal file
152
ports_module/cortex_r4/ac6/example_build/txm/.cproject
Normal file
@@ -0,0 +1,152 @@
|
||||
<?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.519865483">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.519865483" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<externalSettings>
|
||||
<externalSetting>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/txm"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/txm/Debug"/>
|
||||
<entry flags="RESOLVED" kind="libraryFile" name="txm" srcPrefixMapping="" srcRootPath=""/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.debug.519865483" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.519865483." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.lib.debug.808979116" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.lib.debug">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.std" id="com.arm.toolchain.v6.base.options.debug.level.1877486050" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.723936861" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-R4.VFPv3_D16" valueType="string"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.floatabi.979977566" name="Float ABI" superClass="com.arm.toolchain.v6.base.options.floatabi" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.toolchain.v6.base.options.inst.2014027180" name="Instruction set" superClass="com.arm.toolchain.v6.base.options.inst" useByScannerDiscovery="false" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.lib.debug.519865483..1864969534" name=""/>
|
||||
<builder buildPath="${workspace_loc:/txm}/Debug" id="com.arm.toolchain.v6.builder.1850786025" 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.6241967" 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.338050838" 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.1118941673" 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.incpath.973642779" 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_modules}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_generic}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.cpu.220397346" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.target.543594186" name="Target (--target)" superClass="com.arm.tool.c.compiler.v6.base.option.target" useByScannerDiscovery="true" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.fpu.396019355" name="FPU (-mfpu)" superClass="com.arm.tool.c.compiler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.floatabi.1409006855" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.c.compiler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.inst.890112349" name="Instruction set" superClass="com.arm.tool.c.compiler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings.213110718" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.target.enableToolSpecificSettings" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.preproc.enableToolSpecificSettings.1682954929" 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.options.debug.enableToolSpecificSettings.1982558148" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.debug.enableToolSpecificSettings" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.flags.916031554" name="Other flags" superClass="com.arm.tool.c.compiler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="-frwpi"/>
|
||||
<listOptionValue builtIn="false" value="-fropi"/>
|
||||
</option>
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.1705222921" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.1789325577" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.1229585940" 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.880645285" 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.1402765001" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.1631473801" 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.1909393551" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.incpath.2135819939" name="Include path (-I)" superClass="com.arm.tool.assembler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx}""/>
|
||||
</option>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.986031904" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-r4f" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.target.1086548395" name="Target (--target)" superClass="com.arm.tool.assembler.v6.base.option.target" useByScannerDiscovery="false" value="arm-arm-none-eabi" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.fpu.124931130" name="FPU (-mfpu)" superClass="com.arm.tool.assembler.v6.base.option.fpu" useByScannerDiscovery="true" value="vfpv3-d16" valueType="string"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.floatabi.1643867333" name="Float ABI (-mfloat-abi)" superClass="com.arm.tool.assembler.v6.base.option.floatabi" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.floatabi.soft" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.inst.206157906" name="Instruction set" superClass="com.arm.tool.assembler.v6.base.option.inst" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.option.inst.arm" valueType="enumerated"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.options.target.enableToolSpecificSettings.1161924288" name="Enable tool specific settings" superClass="com.arm.tool.assembler.v6.base.options.target.enableToolSpecificSettings" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="com.arm.tool.assembler.v6.base.options.preproc.enableToolSpecificSettings.1861899722" 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.flags.61090532" name="Other flags" superClass="com.arm.tool.assembler.v6.base.option.flags" useByScannerDiscovery="true" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="-fropi"/>
|
||||
<listOptionValue builtIn="false" value="-frwpi"/>
|
||||
</option>
|
||||
<option id="com.arm.tool.assembler.v6.base.option.defmac.1649961135" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac" useByScannerDiscovery="false"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.1161172462" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.2136164467" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6"/>
|
||||
<tool id="com.arm.tool.librarian.v6.1634398245" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings">
|
||||
<externalSettings containerId="tx;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier">
|
||||
<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>
|
||||
</storageModule>
|
||||
</cconfiguration>
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.lib.release.2096916400">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.release.2096916400" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<externalSettings>
|
||||
<externalSetting>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/txm"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/txm/Release"/>
|
||||
<entry flags="RESOLVED" kind="libraryFile" name="txm" srcPrefixMapping="" srcRootPath=""/>
|
||||
</externalSetting>
|
||||
</externalSettings>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.release.2096916400" name="Release" parent="com.arm.eclipse.build.config.v6.lib.release">
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.lib.release.2096916400." name="/" resourcePath="">
|
||||
<toolChain id="com.arm.toolchain.v6.lib.release.775914121" name="Arm Compiler 6 (DS-5 built-in)" superClass="com.arm.toolchain.v6.lib.release">
|
||||
<option defaultValue="com.arm.tool.c.compiler.v6.base.options.debug.level.none" id="com.arm.toolchain.v6.base.options.debug.level.1216865522" name="Debug Level" superClass="com.arm.toolchain.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<targetPlatform id="com.arm.eclipse.build.config.v6.lib.release.2096916400..112800518" name=""/>
|
||||
<builder buildPath="${workspace_loc:/txm}/Release" id="com.arm.toolchain.v6.builder.614719204" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="com.arm.toolchain.v6.builder"/>
|
||||
<tool id="com.arm.tool.c.compiler.v6.1211197993" 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.1084198370" 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.28182833" 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.389178055" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
<inputType id="com.arm.tool.cpp.compiler.v6.base.input.1669523083" superClass="com.arm.tool.cpp.compiler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.730735832" 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.1118429846" 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.1420207151" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.assembler.v6.272655679" 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.753628661" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" valueType="enumerated"/>
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.257137608" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
</tool>
|
||||
<tool id="com.arm.tool.c.linker.v6.680343036" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6"/>
|
||||
<tool id="com.arm.tool.librarian.v6.281403224" 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="txm.com.arm.eclipse.build.project.v6.lib.837111164" 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="/txm"/>
|
||||
</configuration>
|
||||
<configuration configurationName="Release">
|
||||
<resource resourceType="PROJECT" workspacePath="/txm"/>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
</cproject>
|
||||
54
ports_module/cortex_r4/ac6/example_build/txm/.project
Normal file
54
ports_module/cortex_r4/ac6/example_build/txm/.project
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>txm</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>tx</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>inc_generic</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>inc_generic_modules</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common_modules/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>inc_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_generic_module</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common_modules/module_lib/src</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/module_lib/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="com.arm.eclipse.build.config.v6.lib.debug.519865483" 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="1219961745659432110" 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.2096916400" 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="1208898303067000398" 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>
|
||||
360
ports_module/cortex_r4/ac6/inc/tx_port.h
Normal file
360
ports_module/cortex_r4/ac6/inc/tx_port.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
|
||||
/* macro definition, */
|
||||
/* resulting in version 6.1.6 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#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 intrinsics. */
|
||||
|
||||
#include "arm_compat.h"
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX ARM port. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */
|
||||
#else
|
||||
#define TX_INT_DISABLE 0x80 /* Disable IRQ interrupts */
|
||||
#endif
|
||||
#define TX_INT_ENABLE 0x00 /* Enable IRQ interrupts */
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_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_vfp_enable; \
|
||||
VOID *tx_thread_module_instance_ptr; \
|
||||
VOID *tx_thread_module_entry_info_ptr; \
|
||||
ULONG tx_thread_module_current_user_mode; \
|
||||
ULONG tx_thread_module_user_mode; \
|
||||
VOID *tx_thread_module_kernel_stack_start; \
|
||||
VOID *tx_thread_module_kernel_stack_end; \
|
||||
ULONG tx_thread_module_kernel_stack_size; \
|
||||
VOID *tx_thread_module_stack_ptr; \
|
||||
VOID *tx_thread_module_stack_start; \
|
||||
VOID *tx_thread_module_stack_end; \
|
||||
ULONG tx_thread_module_stack_size; \
|
||||
VOID *tx_thread_module_reserved;
|
||||
#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 VOID *tx_event_flags_group_module_instance; \
|
||||
VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
|
||||
VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
|
||||
#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
|
||||
VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
|
||||
#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
/* 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 __thumb
|
||||
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
|
||||
b = (ULONG) __clz((unsigned int) m); \
|
||||
b = 31 - b;
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 __thumb
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save_disabled;
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
|
||||
/* IRQ and FIQ support. */
|
||||
|
||||
#define TX_DISABLE __memory_changed(), interrupt_save_disabled = __disable_irq(); \
|
||||
__disable_fiq();
|
||||
|
||||
#define TX_RESTORE if (!interrupt_save_disabled) \
|
||||
{ \
|
||||
__enable_irq(); \
|
||||
__enable_fiq(); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define TX_DISABLE __memory_changed(), interrupt_save_disabled = __disable_irq();
|
||||
|
||||
#define TX_RESTORE if (!interrupt_save_disabled) \
|
||||
{ \
|
||||
__enable_irq(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
unsigned int _tx_thread_interrupt_disable(void);
|
||||
unsigned int _tx_thread_interrupt_restore(UINT old_posture);
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define VFP extension for the Cortex-R4. Each is assumed to be called in the context of the executing
|
||||
thread. */
|
||||
|
||||
void tx_thread_vfp_enable(void);
|
||||
void tx_thread_vfp_disable(void);
|
||||
|
||||
|
||||
/* Define the 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-R4/AC6 Version 6.1.6 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
366
ports_module/cortex_r4/ac6/inc/txm_module_port.h
Normal file
366
ports_module/cortex_r4/ac6/inc/txm_module_port.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* APPLICATION INTERFACE DEFINITION RELEASE */
|
||||
/* */
|
||||
/* txm_module_port.h Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the basic module constants, interface structures, */
|
||||
/* and function prototypes. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE_PORT_H
|
||||
#define TXM_MODULE_PORT_H
|
||||
|
||||
/* It is assumed that the base ThreadX tx_port.h file has been modified to add the
|
||||
following extensions to the ThreadX thread control block (this code should replace
|
||||
the corresponding macro define in tx_port.h):
|
||||
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; \
|
||||
VOID *tx_thread_module_instance_ptr; \
|
||||
VOID *tx_thread_module_entry_info_ptr; \
|
||||
ULONG tx_thread_module_current_user_mode; \
|
||||
ULONG tx_thread_module_user_mode; \
|
||||
VOID *tx_thread_module_kernel_stack_start; \
|
||||
VOID *tx_thread_module_kernel_stack_end; \
|
||||
ULONG tx_thread_module_kernel_stack_size; \
|
||||
VOID *tx_thread_module_stack_ptr; \
|
||||
VOID *tx_thread_module_stack_start; \
|
||||
VOID *tx_thread_module_stack_end; \
|
||||
ULONG tx_thread_module_stack_size; \
|
||||
VOID *tx_thread_module_reserved;
|
||||
|
||||
The following extensions must also be defined in tx_port.h:
|
||||
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \
|
||||
VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
|
||||
|
||||
#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
|
||||
VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
|
||||
|
||||
#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
|
||||
VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
|
||||
|
||||
#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* Size of module heap. */
|
||||
#define TXM_MODULE_HEAP_SIZE 1024
|
||||
|
||||
/* Define the kernel stack size for a module thread. */
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_SIZE
|
||||
#define TXM_MODULE_KERNEL_STACK_SIZE 1024
|
||||
#endif
|
||||
|
||||
/* Defined, these options allows a memory-protected module to access kernel objects.
|
||||
For example, when a module needs to send/receive a message from a kernel queue.
|
||||
This does not allow modules to create or delete objects outside of their memory.
|
||||
Default setting for these values is undefined. */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_BLOCK_POOL_ACCESS */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_BYTE_POOL_ACCESS */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_EVENT_FLAGS_ACCESS */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_MUTEX_ACCESS */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_QUEUE_ACCESS */
|
||||
/* #define TXM_MODULE_ENABLE_KERNEL_SEMAPHORE_ACCESS */
|
||||
|
||||
|
||||
/* For the following 3 access control settings, change TEX and C, B, S (bits 5 through 0)
|
||||
* to reflect your system memory attributes (cache, shareable, memory type). */
|
||||
/* Code region access control: read-only, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_CODE_ACCESS_CONTROL 0x00000607
|
||||
/* Data region access control: execute never, read/write, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_DATA_ACCESS_CONTROL 0x00001307
|
||||
/* Shared region access control: execute never, read-only, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_SHARED_ACCESS_CONTROL 0x00001207
|
||||
|
||||
/* Define constants specific to the tools the module can be built with for this particular modules port. */
|
||||
|
||||
#define TXM_MODULE_IAR_COMPILER 0x00000000
|
||||
#define TXM_MODULE_RVDS_COMPILER 0x01000000
|
||||
#define TXM_MODULE_GNU_COMPILER 0x02000000
|
||||
#define TXM_MODULE_COMPILER_MASK 0xFF000000
|
||||
#define TXM_MODULE_OPTIONS_MASK 0x000000FF
|
||||
|
||||
|
||||
/* Define the properties for this particular module port. */
|
||||
|
||||
#define TXM_MODULE_MEMORY_PROTECTION_ENABLED
|
||||
|
||||
#ifdef TXM_MODULE_MEMORY_PROTECTION_ENABLED
|
||||
#define TXM_MODULE_REQUIRE_ALLOCATED_OBJECT_MEMORY
|
||||
#define TXM_MODULE_MANAGER_DISABLE_INTERRUPT_CONTROL
|
||||
#else
|
||||
#define TXM_MODULE_REQUIRE_LOCAL_OBJECT_MEMORY
|
||||
#endif
|
||||
|
||||
#define TXM_MODULE_USER_MODE 0x00000001
|
||||
#define TXM_MODULE_MEMORY_PROTECTION 0x00000001
|
||||
|
||||
|
||||
/* Define the supported options for this module. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_SUPPORTED_OPTIONS (TXM_MODULE_MEMORY_PROTECTION)
|
||||
#define TXM_MODULE_MANAGER_REQUIRED_OPTIONS 0
|
||||
|
||||
|
||||
/* Define offset adjustments according to the compiler used to build the module. */
|
||||
|
||||
#define TXM_MODULE_IAR_SHELL_ADJUST 24
|
||||
#define TXM_MODULE_IAR_START_ADJUST 28
|
||||
#define TXM_MODULE_IAR_STOP_ADJUST 32
|
||||
#define TXM_MODULE_IAR_CALLBACK_ADJUST 44
|
||||
|
||||
#define TXM_MODULE_RVDS_SHELL_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_START_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_STOP_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_CALLBACK_ADJUST 0
|
||||
|
||||
#define TXM_MODULE_GNU_SHELL_ADJUST 24
|
||||
#define TXM_MODULE_GNU_START_ADJUST 28
|
||||
#define TXM_MODULE_GNU_STOP_ADJUST 32
|
||||
#define TXM_MODULE_GNU_CALLBACK_ADJUST 44
|
||||
|
||||
|
||||
/* Define other module port-specific constants. */
|
||||
|
||||
|
||||
/* Define INLINE_DECLARE to inline for IAR compiler. */
|
||||
|
||||
#define INLINE_DECLARE inline
|
||||
|
||||
/* Define the number of MPU entries assigned to the code and data sections.
|
||||
On Cortex-R parts, there are 12 total entries. ThreadX uses one for access
|
||||
to the kernel entry function, thus 11 remain for code and data protection. */
|
||||
#define TXM_MODULE_MPU_TOTAL_ENTRIES 12
|
||||
#define TXM_MODULE_MPU_CODE_ENTRIES 4
|
||||
#define TXM_MODULE_MPU_DATA_ENTRIES 4
|
||||
#define TXM_MODULE_MPU_SHARED_ENTRIES 3
|
||||
|
||||
#define TXM_MODULE_MPU_KERNEL_ENTRY_INDEX 0
|
||||
#define TXM_MODULE_MPU_SHARED_INDEX 9
|
||||
|
||||
/* There are 3 registers to set up each MPU region: DRACR, DRBAR, DRSR. */
|
||||
#define TXM_MODULE_MPU_REGISTER_COUNT 3
|
||||
|
||||
#define TXM_ENABLE_REGION 0x01
|
||||
|
||||
/* Shared memory region attributes. */
|
||||
#define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE 1
|
||||
#define TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT 0x00000100
|
||||
|
||||
typedef struct TXM_MODULE_MPU_INFO_STRUCT
|
||||
{
|
||||
ULONG txm_module_mpu_region_address;
|
||||
ULONG txm_module_mpu_region_size;
|
||||
ULONG txm_module_mpu_region_attributes;
|
||||
} TXM_MODULE_MPU_INFO;
|
||||
/* Define the port-extensions to the module manager instance structure. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_PORT_EXTENSION \
|
||||
TXM_MODULE_MPU_INFO txm_module_instance_mpu_registers[TXM_MODULE_MPU_TOTAL_ENTRIES]; \
|
||||
ULONG txm_module_instance_shared_memory_count; \
|
||||
ULONG txm_module_instance_shared_memory_address[TXM_MODULE_MPU_SHARED_ENTRIES]; \
|
||||
ULONG txm_module_instance_shared_memory_length[TXM_MODULE_MPU_SHARED_ENTRIES];
|
||||
|
||||
|
||||
/* Define the memory fault information structure that is populated when a memory fault occurs. */
|
||||
|
||||
|
||||
typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT
|
||||
{
|
||||
TX_THREAD *txm_module_manager_memory_fault_info_thread_ptr;
|
||||
VOID *txm_module_manager_memory_fault_info_code_location;
|
||||
ULONG txm_module_manager_memory_fault_info_dfar;
|
||||
ULONG txm_module_manager_memory_fault_info_dfsr;
|
||||
ULONG txm_module_manager_memory_fault_info_ifar;
|
||||
ULONG txm_module_manager_memory_fault_info_ifsr;
|
||||
ULONG txm_module_manager_memory_fault_info_sp;
|
||||
ULONG txm_module_manager_memory_fault_info_r0;
|
||||
ULONG txm_module_manager_memory_fault_info_r1;
|
||||
ULONG txm_module_manager_memory_fault_info_r2;
|
||||
ULONG txm_module_manager_memory_fault_info_r3;
|
||||
ULONG txm_module_manager_memory_fault_info_r4;
|
||||
ULONG txm_module_manager_memory_fault_info_r5;
|
||||
ULONG txm_module_manager_memory_fault_info_r6;
|
||||
ULONG txm_module_manager_memory_fault_info_r7;
|
||||
ULONG txm_module_manager_memory_fault_info_r8;
|
||||
ULONG txm_module_manager_memory_fault_info_r9;
|
||||
ULONG txm_module_manager_memory_fault_info_r10;
|
||||
ULONG txm_module_manager_memory_fault_info_r11;
|
||||
ULONG txm_module_manager_memory_fault_info_r12;
|
||||
ULONG txm_module_manager_memory_fault_info_lr;
|
||||
ULONG txm_module_manager_memory_fault_info_cpsr;
|
||||
} TXM_MODULE_MANAGER_MEMORY_FAULT_INFO;
|
||||
|
||||
|
||||
#define TXM_MODULE_MANAGER_FAULT_INFO \
|
||||
TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info;
|
||||
|
||||
/* Define the macro to check the stack available in dispatch. */
|
||||
#define TXM_MODULE_MANAGER_CHECK_STACK_AVAILABLE
|
||||
|
||||
/* Define the macro to check the module properties. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_CHECK_PROPERTIES(properties) \
|
||||
if ((properties & _txm_module_manager_properties_supported) != (properties & ~((ULONG) TXM_MODULE_COMPILER_MASK))) \
|
||||
{ \
|
||||
_tx_mutex_put(&_txm_module_manager_mutex); \
|
||||
return(TXM_MODULE_INVALID_PROPERTIES); \
|
||||
} \
|
||||
if ((_txm_module_manager_properties_required & properties) != _txm_module_manager_properties_required) \
|
||||
{ \
|
||||
_tx_mutex_put(&_txm_module_manager_mutex); \
|
||||
return(TXM_MODULE_INVALID_PROPERTIES); \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to check the code alignment. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) \
|
||||
{ \
|
||||
ULONG temp; \
|
||||
temp = (ULONG) module_location; \
|
||||
temp = temp & (code_alignment - 1); \
|
||||
if (temp) \
|
||||
{ \
|
||||
_tx_mutex_put(&_txm_module_manager_mutex); \
|
||||
return(TXM_MODULE_ALIGNMENT_ERROR); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to adjust the alignment and size for code/data areas. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size, data_alignment) _txm_module_manager_alignment_adjust(module_preamble, &code_size, &code_alignment, &data_size, &data_alignment);
|
||||
|
||||
|
||||
/* Define the macro to adjust the symbols in the module preamble. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(properties, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust) \
|
||||
if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_IAR_COMPILER) \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_IAR_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_IAR_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_IAR_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_IAR_CALLBACK_ADJUST; \
|
||||
} \
|
||||
else if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_RVDS_COMPILER) \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_RVDS_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_RVDS_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_RVDS_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_RVDS_CALLBACK_ADJUST; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_GNU_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_GNU_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_GNU_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_GNU_CALLBACK_ADJUST; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to populate the thread control block with module port-specific information.
|
||||
Check if the module is in user mode and set up txm_module_thread_entry_info_kernel_call_dispatcher accordingly.
|
||||
*/
|
||||
|
||||
#define TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance) \
|
||||
thread_ptr -> tx_thread_module_current_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION; \
|
||||
thread_ptr -> tx_thread_module_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION; \
|
||||
if (thread_ptr -> tx_thread_module_user_mode) \
|
||||
{ \
|
||||
thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_user_mode_entry; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_kernel_dispatch; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to populate the module control block with module port-specific information.
|
||||
If memory protection is enabled, set up the MPU registers.
|
||||
*/
|
||||
#define TXM_MODULE_MANAGER_MODULE_SETUP(module_instance) \
|
||||
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) \
|
||||
{ \
|
||||
_txm_module_manager_mm_register_setup(module_instance); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Do nothing. */ \
|
||||
}
|
||||
|
||||
/* Define the macro to perform port-specific functions when unloading the module. */
|
||||
/* Nothing needs to be done for this port. */
|
||||
#define TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance)
|
||||
|
||||
|
||||
/* Define the macros to perform port-specific checks when passing pointers to the kernel. */
|
||||
|
||||
/* Define macro to make sure object is inside the module's data. */
|
||||
#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \
|
||||
_txm_module_manager_inside_data_check(module_instance, obj_ptr, obj_size)
|
||||
|
||||
|
||||
/* Define some internal prototypes to this module port. */
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define txm_module_manager_memory_fault_notify _txm_module_manager_memory_fault_notify
|
||||
#endif
|
||||
|
||||
|
||||
#define TXM_MODULE_MANAGER_ADDITIONAL_PROTOTYPES \
|
||||
VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment); \
|
||||
ULONG _txm_module_manager_data_pointer_check(TXM_MODULE_INSTANCE *module_instance, ULONG pointer); \
|
||||
VOID _txm_module_manager_memory_fault_handler(VOID); \
|
||||
UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)); \
|
||||
VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \
|
||||
ULONG _txm_power_of_two_block_size(ULONG size); \
|
||||
ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length); \
|
||||
ULONG _txm_module_manager_region_size_get(ULONG block_size); \
|
||||
UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size);
|
||||
|
||||
#define TXM_MODULE_MANAGER_VERSION_ID \
|
||||
CHAR _txm_module_manager_version_id[] = \
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Module Cortex-R4/MPU/ARM Version 6.1 *";
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/** Module */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
;#define TX_SOURCE_CODE
|
||||
;
|
||||
;
|
||||
;/* Include necessary system files. */
|
||||
;
|
||||
;#include "tx_api.h"
|
||||
;#include "tx_thread.h"
|
||||
|
||||
|
||||
|
||||
.global __scatterload
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
.eabi_attribute Tag_ABI_PCS_RO_data, 1
|
||||
.eabi_attribute Tag_ABI_PCS_R9_use, 1
|
||||
.eabi_attribute Tag_ABI_PCS_RW_data, 2
|
||||
.arm
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_initialize Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function initializes the module c runtime. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* heap_base Pointer to bottom of heap */
|
||||
/* heap_top Pointer to top of heap */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* __scatterload Initialize C runtime */
|
||||
/* __rt_lib_init Initialize heap */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Start module thread */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _txm_module_initialize(VOID *heap_base, VOID *heap_top) */
|
||||
.global _txm_module_initialize
|
||||
.type _txm_module_initialize, %function
|
||||
|
||||
_txm_module_initialize:
|
||||
PUSH {r0-r12,lr} // Save dregs and LR
|
||||
|
||||
B __scatterload // Call ARM func to initialize variables
|
||||
|
||||
|
||||
.global __rt_entry
|
||||
.type __rt_entry, %function
|
||||
__rt_entry:
|
||||
POP {r0-r1}
|
||||
BL __rt_lib_init
|
||||
POP {r2-r12,lr} // Restore dregs and LR
|
||||
BX lr // Return to caller
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE
|
||||
#define TXM_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define TX_SOURCE_CODE
|
||||
#endif
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "txm_module.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/* Define the global module entry pointer from the start thread of the module. */
|
||||
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
|
||||
|
||||
|
||||
/* Define the dispatch function pointer used in the module implementation. */
|
||||
|
||||
ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
|
||||
|
||||
/* Define the module's heap and align it to 8 bytes. */
|
||||
__attribute__((aligned(8))) UCHAR txm_heap[TXM_MODULE_HEAP_SIZE];
|
||||
|
||||
/* Must use two region memory - heap and stack are not next to each other. */
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
|
||||
/* Use our asm routine that calls the ARM code to initialize data and heap. */
|
||||
extern VOID _txm_module_initialize(VOID *heap_base, VOID *heap_top);
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calls the specified entry function of the thread. It */
|
||||
/* also provides a place for the thread's entry function to return. */
|
||||
/* If the thread returns, this function places the thread in a */
|
||||
/* "COMPLETED" state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to current thread */
|
||||
/* thread_info Pointer to thread entry info */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_initialize cstartup initialization */
|
||||
/* thread_entry Thread's entry function */
|
||||
/* tx_thread_resume Resume the module callback thread */
|
||||
/* _txm_module_thread_system_suspend Module thread suspension routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*entry_exit_notify)(TX_THREAD *, UINT);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if this is the start thread. If so, we must prepare the module for
|
||||
execution. If not, simply skip the C startup code. */
|
||||
if (thread_info -> txm_module_thread_entry_info_start_thread)
|
||||
{
|
||||
/* Initialize the ARM C environment. */
|
||||
_txm_module_initialize(&txm_heap[0], &txm_heap[TXM_MODULE_HEAP_SIZE-1]);
|
||||
|
||||
/* Save the entry info pointer, for later use. */
|
||||
_txm_module_entry_info = thread_info;
|
||||
|
||||
/* Save the kernel function dispatch address. This is used to make all resident calls from
|
||||
the module. */
|
||||
_txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
|
||||
|
||||
/* Ensure that we have a valid pointer. */
|
||||
while (!_txm_module_kernel_call_dispatcher)
|
||||
{
|
||||
/* Loop here, if an error is present getting the dispatch function pointer!
|
||||
An error here typically indicates the resident portion of _tx_thread_schedule
|
||||
is not supporting the trap to obtain the function pointer. */
|
||||
}
|
||||
|
||||
/* Resume the module's callback thread, already created in the manager. */
|
||||
_txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
|
||||
}
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has been entered! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call current thread's entry function. */
|
||||
(thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
|
||||
|
||||
/* Suspend thread with a "completed" state. */
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine again. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has exited! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_txm_module_thread_system_suspend(thread_ptr);
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
|
||||
/* If we ever get here, raise safety critical exception. */
|
||||
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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"
|
||||
*/
|
||||
|
||||
|
||||
#define IRQ_MODE 0x12 // IRQ mode
|
||||
#define SYS_MODE 0x1F // SYS mode
|
||||
#define THUMB_MASK 0x20 // Thumb bit mask
|
||||
|
||||
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_execute_ptr
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_thread_schedule
|
||||
.global _tx_thread_preempt_disable
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_isr_exit
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the interrupt context if it is processing a */
|
||||
/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||
/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||
/* if no thread was running, the function returns to the scheduler. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_restore(VOID)
|
||||
{ */
|
||||
.global _tx_thread_context_restore
|
||||
.type _tx_thread_context_restore, "function"
|
||||
_tx_thread_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
|
||||
#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 r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3, #0] // Pickup system state
|
||||
SUB r2, r2, #1 // Decrement the counter
|
||||
STR r2, [r3, #0] // Store the counter
|
||||
CMP r2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} // Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 // Put SPSR back
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
SUBS pc, lr, #0 // 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 r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] // Pickup actual current thread pointer
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted
|
||||
|
||||
LDR r3, =_tx_thread_preempt_disable // Pickup preempt disable address
|
||||
LDR r2, [r3, #0] // Pickup actual preempt disable flag
|
||||
CMP r2, #0 // Is it set?
|
||||
BNE __tx_thread_no_preempt_restore // Yes, don't preempt this thread
|
||||
LDR r3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR r2, [r3, #0] // Pickup actual execute thread pointer
|
||||
CMP r0, r2 // Is the same thread highest priority?
|
||||
BNE __tx_thread_preempt_restore // No, preemption needs to happen
|
||||
|
||||
|
||||
__tx_thread_no_preempt_restore:
|
||||
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
/* tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} // Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 // Put SPSR back
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
SUBS pc, lr, #0 // Return to point of interrupt
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
LDMIA sp!, {r3, r10, r12, lr} // Recover temporarily saved registers
|
||||
MOV r1, lr // Save lr (point of interrupt)
|
||||
CPS #SYS_MODE // Switch to SYS mode to save context on thread stack
|
||||
STR r1, [sp, #-4]! // Save point of interrupt
|
||||
STMDB sp!, {r4-r12, lr} // Save registers
|
||||
MOV r4, r3 // Save SPSR in r4
|
||||
|
||||
CPS #IRQ_MODE // Switch back to IRQ mode
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
|
||||
CPS #SYS_MODE // Switch to SYS mode to save remaining context on thread stack
|
||||
STMDB sp!, {r0-r3} // Save r0-r3 on thread's stack
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] // Pickup current thread pointer
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r2, [r0, #144] // Pickup the VFP enabled flag
|
||||
CMP r2, #0 // Is the VFP enabled?
|
||||
BEQ _tx_skip_irq_vfp_save // No, skip VFP IRQ save
|
||||
VMRS r2, FPSCR // Pickup the FPSCR
|
||||
STR r2, [sp, #-4]! // Save FPSCR
|
||||
VSTMDB sp!, {D0-D15} // Save D0-D15
|
||||
_tx_skip_irq_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r3, #1 // Build interrupt stack type
|
||||
STMDB sp!, {r3, r4} // Save interrupt stack type and SPSR
|
||||
STR sp, [r0, #8] // Save stack pointer in thread control
|
||||
// block
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
LDR r3, =_tx_timer_time_slice // Pickup time-slice variable address
|
||||
LDR r2, [r3, #0] // Pickup time-slice
|
||||
CMP r2, #0 // Is it active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save it
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; */
|
||||
/* _tx_timer_time_slice = 0; */
|
||||
|
||||
STR r2, [r0, #24] // Save thread's time-slice
|
||||
MOV r2, #0 // Clear value
|
||||
STR r2, [r3, #0] // Disable global time-slice flag
|
||||
|
||||
/* } */
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
MOV r0, #0 // NULL value
|
||||
STR r0, [r1, #0] // Clear current thread pointer
|
||||
|
||||
/* Return to the scheduler. */
|
||||
/* _tx_thread_schedule(); */
|
||||
|
||||
CPS #IRQ_MODE // Enter IRQ mode
|
||||
MRS r1, SPSR // Get SPSR
|
||||
ORR r1, r1, #SYS_MODE // Change to SYS Mode
|
||||
BIC r1, r1, #THUMB_MASK // Clear thumb bit
|
||||
MSR SPSR_cxsf, r1 // Put SYS Mode in SPSR
|
||||
LDR lr, =_tx_thread_schedule // Load scheduler address
|
||||
SUBS pc, lr, #0 // Return to scheduler
|
||||
/* } */
|
||||
|
||||
__tx_thread_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
LDR lr, =_tx_thread_schedule // Load scheduler address
|
||||
SUBS pc, lr, #0 // Return to scheduler
|
||||
/* } */
|
||||
@@ -0,0 +1,202 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global __tx_irq_processing_return
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_isr_enter
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_save(VOID)
|
||||
{ */
|
||||
.global _tx_thread_context_save
|
||||
.type _tx_thread_context_save, "function"
|
||||
_tx_thread_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, and all registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++)
|
||||
{ */
|
||||
|
||||
STMDB sp!, {r0-r3} // Save some working registers
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable FIQ interrupts
|
||||
#endif
|
||||
LDR r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3, #0] // Pickup system state
|
||||
CMP r2, #0 // Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save // Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3, #0] // Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
MRS r0, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} // Store other registers
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return // Continue IRQ processing
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr)
|
||||
{ */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3, #0] // Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] // Pickup current thread pointer
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save // If so, interrupt occurred in
|
||||
// scheduling loop - nothing needs saving!
|
||||
|
||||
/* Save minimal context of interrupted thread. */
|
||||
|
||||
MRS r2, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r2, r10, r12, lr} // Store other registers
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return // Continue IRQ processing
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
|
||||
__tx_thread_idle_system_save:
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
/* Not much to do here, just adjust the stack pointer, and return to IRQ
|
||||
processing. */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #16 // Recover saved registers
|
||||
B __tx_irq_processing_return // Continue IRQ processing
|
||||
|
||||
/* } */
|
||||
/* } */
|
||||
@@ -0,0 +1,260 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
#define FIQ_MODE 0x11 // FIQ mode
|
||||
#define SVC_MODE 0x13 // SVC mode
|
||||
#define MODE_MASK 0x1F // Mode mask
|
||||
#define IRQ_MODE_BITS 0x12 // IRQ mode bits
|
||||
|
||||
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_thread_execute_ptr
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_thread_schedule
|
||||
.global _tx_thread_preempt_disable
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_isr_exit
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_context_restore Cortex-R4/AC6 */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the fiq interrupt context when 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 */
|
||||
/* */
|
||||
/* FIQ ISR Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_context_restore(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_fiq_context_restore
|
||||
.type _tx_thread_fiq_context_restore, "function"
|
||||
_tx_thread_fiq_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
CPSID if // Disable IRQ and FIQ 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 r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3] // Pickup system state
|
||||
SUB r2, r2, #1 // Decrement the counter
|
||||
STR r2, [r3] // Store the counter
|
||||
CMP r2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_fiq_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} // Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 // Put SPSR back
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
SUBS pc, lr, #0 // Return to point of interrupt
|
||||
|
||||
|
||||
/* } */
|
||||
__tx_thread_fiq_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 r1, [sp] // Pickup the saved SPSR
|
||||
MOV r2, #MODE_MASK // Build mask to isolate the interrupted mode
|
||||
AND r1, r1, r2 // Isolate mode bits
|
||||
CMP r1, #IRQ_MODE_BITS // Was an interrupt taken in IRQ mode before we
|
||||
// got to context save? */
|
||||
BEQ __tx_thread_fiq_no_preempt_restore // Yes, just go back to point of interrupt
|
||||
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1] // Pickup actual current thread pointer
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_fiq_idle_system_restore // Yes, idle system was interrupted
|
||||
|
||||
LDR r3, =_tx_thread_preempt_disable // Pickup preempt disable address
|
||||
LDR r2, [r3] // Pickup actual preempt disable flag
|
||||
CMP r2, #0 // Is it set?
|
||||
BNE __tx_thread_fiq_no_preempt_restore // Yes, don't preempt this thread
|
||||
LDR r3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR r2, [r3] // Pickup actual execute thread pointer
|
||||
CMP r0, r2 // Is the same thread highest priority?
|
||||
BNE __tx_thread_fiq_preempt_restore // No, preemption needs to happen
|
||||
|
||||
|
||||
__tx_thread_fiq_no_preempt_restore:
|
||||
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
/* tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, lr} // Recover SPSR and POI
|
||||
MSR SPSR_cxsf, r0 // Put SPSR back
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
SUBS pc, lr, #0 // Return to point of interrupt
|
||||
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
__tx_thread_fiq_preempt_restore:
|
||||
|
||||
LDMIA sp!, {r3, lr} // Recover temporarily saved registers
|
||||
MOV r1, lr // Save lr (point of interrupt)
|
||||
|
||||
CPS #SVC_MODE // Switch to SVC mode to save context on thread stack
|
||||
STR r1, [sp, #-4]! // Save point of interrupt
|
||||
STMDB sp!, {r4-r12, lr} // Save upper half of registers
|
||||
MOV r4, r3 // Save SPSR in r4
|
||||
|
||||
CPS #FIQ_MODE // Switch back to FIQ mode
|
||||
LDMIA sp!, {r0-r3} // Recover r0-r3
|
||||
|
||||
CPS #SVC_MODE // Switch to SVC mode to save remaining context on thread stack
|
||||
STMDB sp!, {r0-r3} // Save r0-r3 on thread's stack
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1] // Pickup current thread pointer
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r2, [r0, #144] // Pickup the VFP enabled flag
|
||||
CMP r2, #0 // Is the VFP enabled?
|
||||
BEQ _tx_skip_fiq_vfp_save // No, skip VFP FIQ save
|
||||
VMRS r2, FPSCR // Pickup the FPSCR
|
||||
STR r2, [sp, #-4]! // Save FPSCR
|
||||
VSTMDB sp!, {D0-D15} // Save D0-D15
|
||||
_tx_skip_fiq_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r3, #1 // Build interrupt stack type
|
||||
STMDB sp!, {r3, r4} // Save interrupt stack type and SPSR
|
||||
STR sp, [r0, #8] // Save stack pointer in thread control
|
||||
// block
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
/* if (_tx_timer_time_slice) */
|
||||
/* { */
|
||||
|
||||
LDR r3, =_tx_timer_time_slice // Pickup time-slice variable address
|
||||
LDR r2, [r3] // Pickup time-slice
|
||||
CMP r2, #0 // Is it active?
|
||||
BEQ __tx_thread_fiq_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 r2, [r0, #24] // Save thread's time-slice
|
||||
MOV r2, #0 // Clear value
|
||||
STR r2, [r3] // Disable global time-slice flag
|
||||
|
||||
/* } */
|
||||
__tx_thread_fiq_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
MOV r0, #0 // NULL value
|
||||
STR r0, [r1] // Clear current thread pointer
|
||||
|
||||
/* Return to the scheduler. */
|
||||
/* _tx_thread_schedule(); */
|
||||
|
||||
B _tx_thread_schedule // Return to scheduler
|
||||
/* } */
|
||||
|
||||
__tx_thread_fiq_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
ADD sp, sp, #24 // Recover FIQ stack space
|
||||
CPS #SVC_MODE // Switch to SVC mode
|
||||
B _tx_thread_schedule // Return to scheduler
|
||||
|
||||
/* } */
|
||||
@@ -0,0 +1,209 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global __tx_fiq_processing_return
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_isr_enter
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_context_save Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_context_save(VOID) */
|
||||
/* { */
|
||||
|
||||
.global _tx_thread_fiq_context_save
|
||||
.type _tx_thread_fiq_context_save, "function"
|
||||
_tx_thread_fiq_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, and all registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++) */
|
||||
/* { */
|
||||
|
||||
STMDB sp!, {r0-r3} // Save some working registers
|
||||
LDR r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3] // Pickup system state
|
||||
CMP r2, #0 // Is this the first interrupt?
|
||||
BEQ __tx_thread_fiq_not_nested_save // Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3] // Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
MRS r0, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} // Store other registers
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_fiq_processing_return // Continue FIQ processing
|
||||
|
||||
__tx_thread_fiq_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr) */
|
||||
/* { */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3] // Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1] // Pickup current thread pointer
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_fiq_idle_system_save // If so, interrupt occurred in
|
||||
// scheduling loop - nothing needs saving!
|
||||
|
||||
/* Save minimal context of interrupted thread. */
|
||||
|
||||
MRS r2, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r2, lr} // Store other registers, Note that we don't
|
||||
// need to save sl and ip since FIQ has
|
||||
// copies of these registers. Nested
|
||||
// interrupt processing does need to save
|
||||
// these registers.
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_fiq_processing_return // Continue FIQ processing
|
||||
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
|
||||
__tx_thread_fiq_idle_system_save:
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
/* Not much to do here, save the current SPSR and LR for possible
|
||||
use in IRQ interrupted in idle system conditions, and return to
|
||||
FIQ interrupt processing. */
|
||||
|
||||
MRS r0, SPSR // Pickup saved SPSR
|
||||
SUB lr, lr, #4 // Adjust point of interrupt
|
||||
STMDB sp!, {r0, lr} // Store other registers that will get used
|
||||
// or stripped off the stack in context
|
||||
// restore
|
||||
B __tx_fiq_processing_return // Continue FIQ processing
|
||||
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#define FIQ_MODE 0x11 // FIQ Mode bits
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_nesting_end Cortex-R4/AC6 */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from FIQ mode after */
|
||||
/* _tx_thread_fiq_nesting_start has been called and switches the FIQ */
|
||||
/* processing from system mode back to FIQ mode prior to the ISR */
|
||||
/* calling _tx_thread_fiq_context_restore. Note that this function */
|
||||
/* assumes the system stack pointer is in the same position after */
|
||||
/* nesting start function was called. */
|
||||
/* */
|
||||
/* This function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
/* */
|
||||
/* This function returns with FIQ interrupts disabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_nesting_end(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_fiq_nesting_end
|
||||
.type _tx_thread_fiq_nesting_end, "function"
|
||||
_tx_thread_fiq_nesting_end:
|
||||
MOV r3, lr // Save ISR return address
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r1, lr} // Pickup saved lr (and r1 throw-away for
|
||||
// 8-byte alignment logic)
|
||||
CPS #FIQ_MODE // Switch back to FIQ mode
|
||||
BX r3 // Return to caller
|
||||
/* } */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
#define SYS_MODE 0x12 // System mode
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_nesting_start Cortex-R4/AC6 */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from FIQ mode after */
|
||||
/* _tx_thread_fiq_context_save has been called and switches the FIQ */
|
||||
/* processing to the system mode so nested FIQ interrupt processing */
|
||||
/* is possible (system mode has its own "lr" register). Note that */
|
||||
/* this function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
/* */
|
||||
/* This function returns with FIQ interrupts enabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_nesting_start(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_fiq_nesting_start
|
||||
.type _tx_thread_fiq_nesting_start, "function"
|
||||
_tx_thread_fiq_nesting_start:
|
||||
MOV r3, lr // Save ISR return address
|
||||
CPS #SYS_MODE // Switch to system mode
|
||||
STMDB sp!, {r1, lr} // Push the system mode lr on the system mode stack
|
||||
// and push r1 just to keep 8-byte alignment
|
||||
CPSIE f // Enable FIQ interrupts
|
||||
BX r3 // Return to caller
|
||||
/* } */
|
||||
@@ -0,0 +1,102 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#define INT_MASK 0xC0 // Interrupt bit mask
|
||||
#else
|
||||
#define INT_MASK 0x80 // Interrupt bit mask
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.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 r3, CPSR // Pickup current CPSR
|
||||
BIC r1, r3, #INT_MASK // Clear interrupt lockout bits
|
||||
ORR r1, r1, r0 // Or-in new interrupt lockout bits
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
MSR CPSR_c, r1 // Setup new CPSR
|
||||
AND r0, r3, #INT_MASK // Return previous interrupt mask
|
||||
BX lr // Return to caller
|
||||
|
||||
/* } */
|
||||
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_disable Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.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 r0, CPSR // Pickup current CPSR
|
||||
|
||||
/* Mask interrupts. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ
|
||||
#else
|
||||
CPSID i // Disable IRQ
|
||||
#endif
|
||||
|
||||
BX lr // Return to caller
|
||||
|
||||
/* } */
|
||||
@@ -0,0 +1,90 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_restore Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* UINT _tx_thread_interrupt_restore(UINT old_posture) */
|
||||
/* { */
|
||||
.global _tx_thread_interrupt_restore
|
||||
.type _tx_thread_interrupt_restore, "function"
|
||||
_tx_thread_interrupt_restore:
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
MSR CPSR_c, r0 // Setup new CPSR
|
||||
BX lr // Return to caller
|
||||
/* } */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#define IRQ_MODE 0x12 // IRQ Mode bits
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_irq_nesting_end Cortex-R4/AC6 */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from IRQ mode after */
|
||||
/* _tx_thread_irq_nesting_start has been called and switches the IRQ */
|
||||
/* processing from system mode back to IRQ mode prior to the ISR */
|
||||
/* calling _tx_thread_context_restore. Note that this function */
|
||||
/* assumes the system stack pointer is in the same position after */
|
||||
/* nesting start function was called. */
|
||||
/* */
|
||||
/* This function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
/* */
|
||||
/* This function returns with IRQ interrupts disabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_irq_nesting_end(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_irq_nesting_end
|
||||
.type _tx_thread_irq_nesting_end, "function"
|
||||
_tx_thread_irq_nesting_end:
|
||||
MOV r3, lr // Save ISR return address
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r1, lr} // Pickup saved lr (and r1 throw-away for
|
||||
// 8-byte alignment logic)
|
||||
CPS #IRQ_MODE // Switch back to IRQ mode
|
||||
BX r3 // Return to caller
|
||||
/* } */
|
||||
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
#define SYS_MODE 0x1F // System mode bits
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_irq_nesting_start Cortex-R4/AC6 */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from IRQ mode after */
|
||||
/* _tx_thread_context_save has been called and switches the IRQ */
|
||||
/* processing to the system mode so nested IRQ interrupt processing */
|
||||
/* is possible (system mode has its own "lr" register). Note that */
|
||||
/* this function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
/* */
|
||||
/* This function returns with IRQ interrupts enabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_irq_nesting_start(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_irq_nesting_start
|
||||
.type _tx_thread_irq_nesting_start, "function"
|
||||
_tx_thread_irq_nesting_start:
|
||||
MOV r3, lr // Save ISR return address
|
||||
CPS #SYS_MODE // Switch to System Mode
|
||||
STMDB sp!, {r1, lr} // Push the system mode lr on the system mode stack
|
||||
// and push r1 just to keep 8-byte alignment
|
||||
CPSIE i // Enable IRQ interrupts
|
||||
BX r3 // Return to caller
|
||||
/* } */
|
||||
@@ -0,0 +1,469 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
.global _tx_thread_execute_ptr
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_timer_time_slice
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_thread_enter
|
||||
#endif
|
||||
|
||||
#define THUMB_MASK 0x20 // Thumb bit (5) of CPSR/SPSR.
|
||||
#define IRQ_MODE 0x12 // IRQ mode
|
||||
#define USR_MODE 0x10 // USR mode
|
||||
#define SVC_MODE 0x13 // SVC mode
|
||||
#define SYS_MODE 0x1F // SYS mode
|
||||
#define MODE_MASK 0x1F // Mode mask
|
||||
.arm
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_schedule(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_schedule
|
||||
.type _tx_thread_schedule, "function"
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* Enter the scheduler. */
|
||||
SVC 0
|
||||
|
||||
/* We should never get here - ever! */
|
||||
_tx_scheduler_fault__:
|
||||
B _tx_scheduler_fault__
|
||||
/* } */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* SWI_Handler */
|
||||
/**************************************************************************/
|
||||
|
||||
.global SWI_Handler
|
||||
.type SWI_Handler, "function"
|
||||
.global __tx_svc_interrupt
|
||||
.type __tx_svc_interrupt, "function"
|
||||
SWI_Handler:
|
||||
__tx_svc_interrupt:
|
||||
STMFD sp!, {r0-r3, r12, lr} // Store the registers
|
||||
MOV r1, sp // Set pointer to parameters
|
||||
MRS r0, spsr // Get spsr
|
||||
STMFD sp!, {r0, r3} // Store spsr onto stack and another
|
||||
// register to maintain 8-byte-aligned stack
|
||||
TST r0, #THUMB_MASK // Occurred in Thumb state?
|
||||
LDRHNE r0, [lr,#-2] // Yes: Load halfword and...
|
||||
BICNE r0, r0, #0xFF00 // ...extract comment field
|
||||
LDREQ r0, [lr,#-4] // No: Load word and...
|
||||
BICEQ r0, r0, #0xFF000000 // ...extract comment field
|
||||
|
||||
// r0 now contains SVC number
|
||||
// r1 now contains pointer to stacked registers
|
||||
|
||||
CMP r0, #0 // Is it a schedule request?
|
||||
BEQ _tx_handler_svc_schedule // Yes, go there
|
||||
|
||||
CMP r0, #1 // Is it a system mode enter request?
|
||||
BEQ _tx_handler_svc_super_enter // Yes, go there
|
||||
|
||||
CMP r0, #2 // Is it a system mode exit request?
|
||||
BEQ _tx_handler_svc_super_exit // Yes, go there
|
||||
|
||||
LDR r2, =0x123456
|
||||
CMP r0, r2 // Is it an ARM request?
|
||||
BEQ _tx_handler_svc_arm // Yes, go there
|
||||
|
||||
/**************************************************************************/
|
||||
/* Unknown SVC argument */
|
||||
/**************************************************************************/
|
||||
/* Unrecognized service call */
|
||||
_tx_handler_svc_unrecognized:
|
||||
|
||||
_tx_handler_svc_unrecognized_loop: /* We should never get here */
|
||||
B _tx_handler_svc_unrecognized_loop
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* SVC 1 */
|
||||
/**************************************************************************/
|
||||
/* At this point we have an SVC 1, which means we are entering
|
||||
supervisor mode to service a kernel call. */
|
||||
_tx_handler_svc_super_enter:
|
||||
// Make sure that we have been called from the system mode enter location (security).
|
||||
LDR r2, =_txm_system_mode_enter // Load the address of the known call point
|
||||
SUB r1, lr, #4 // Calculate the address of the actual call
|
||||
CMP r1, r2 // Did we come from txm_module_manager_user_mode_entry?
|
||||
BNE _tx_handler_svc_unrecognized // Return to where we came
|
||||
|
||||
// Clear the user mode flag in the thread structure.
|
||||
LDR r1, =_tx_thread_current_ptr // Load the current thread pointer address
|
||||
LDR r2, [r1] // Load current thread location from the pointer (pointer indirection)
|
||||
MOV r1, #0 // Load the new user mode flag value (user mode flag clear -> not user mode -> system)
|
||||
STR r1, [r2, #0x9C] // Clear the current user mode selection for thread
|
||||
|
||||
// Now we enter the system mode and return.
|
||||
LDMFD sp!, {r0, r3} // Get spsr from the stack
|
||||
BIC r0, r0, #MODE_MASK // clear mode field
|
||||
ORR r0, r0, #SYS_MODE // system mode code
|
||||
MSR SPSR_cxsf, r0 // Restore the spsr
|
||||
|
||||
LDR r1, [r2, #0xA8] // Load the module kernel stack pointer
|
||||
CPS #SYS_MODE // Switch to SYS mode
|
||||
MOV r3, sp // Grab thread stack pointer
|
||||
MOV sp, r1 // Set SP to kernel stack pointer
|
||||
CPS #SVC_MODE // Switch back to SVC mode
|
||||
STR r3, [r2, #0xB0] // Save thread stack pointer
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r3, [r2, #0xAC] // Load the module kernel stack size
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
LDRD r0, r1, [r2, #0xA4] // Load the module kernel stack start and end
|
||||
STRD r0, r1, [r2, #0x0C] // Set stack start and end
|
||||
#endif
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ // Restore the registers and return
|
||||
|
||||
/**************************************************************************/
|
||||
/* SVC 2 */
|
||||
/**************************************************************************/
|
||||
/* At this point we have an SVC 2, which means we are exiting
|
||||
supervisor mode after servicing a kernel call. */
|
||||
_tx_handler_svc_super_exit:
|
||||
// Make sure that we have been called from the system mode exit location (security).
|
||||
LDR r2, =_txm_system_mode_exit // Load the address of the known call point
|
||||
SUB r1, lr, #4 // Calculate the address of the actual call
|
||||
CMP r1, r2 // Did we come from txm_module_manager_user_mode_entry?
|
||||
BNE _tx_handler_svc_unrecognized // Return to where we came
|
||||
|
||||
// Set the user mode flag into the thread structure.
|
||||
LDR r1, =_tx_thread_current_ptr // Load the current thread pointer address
|
||||
LDR r2, [r1] // Load the current thread location from the pointer (pointer indirection)
|
||||
MOV r1, #1 // Load the new user mode flag value (user mode enabled -> not system anymore)
|
||||
STR r1, [r2, #0x9C] // Clear the current user mode selection for thread
|
||||
|
||||
// Now we enter user mode (exit the system mode) and return.
|
||||
LDMFD sp!, {r0, r3} // Get spsr from the stack
|
||||
BIC r0, r0, #MODE_MASK // clear mode field
|
||||
ORR r0, r0, #USR_MODE // user mode code
|
||||
MSR SPSR_cxsf, r0 // Restore the spsr
|
||||
|
||||
LDR r1, [r2, #0xB0] // Load the module thread stack pointer
|
||||
CPS #SYS_MODE // Switch to SYS mode
|
||||
MOV sp, r1 // Set SP back to thread stack pointer
|
||||
CPS #SVC_MODE // Switch back to SVC mode
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r3, [r2, #0xBC] // Load the module thread stack size
|
||||
STR r3, [r2, #20] // Set stack size
|
||||
LDRD r0, r1, [r2, #0xB4] // Load the module thread stack start and end
|
||||
STRD r0, r1, [r2, #0x0C] // Set stack start and end
|
||||
#endif
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ // Restore the registers and return
|
||||
|
||||
/**************************************************************************/
|
||||
/* ARM Semihosting */
|
||||
/**************************************************************************/
|
||||
_tx_handler_svc_arm:
|
||||
|
||||
/**** TODO: handle semihosting requests or ARM angel requests ****/
|
||||
|
||||
/* Just return. */
|
||||
LDMFD sp!, {r0, r3} // Get spsr from the stack
|
||||
MSR SPSR_cxsf, r0 // Restore the spsr
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ // Restore the registers and return
|
||||
|
||||
/**************************************************************************/
|
||||
/* SVC 0 */
|
||||
/**************************************************************************/
|
||||
/* At this point we have an SVC 0: enter the scheduler. */
|
||||
_tx_handler_svc_schedule:
|
||||
|
||||
LDMFD sp!, {r0, r3} // Get spsr from stack
|
||||
MSR SPSR_cxsf, r0 // Restore spsr
|
||||
LDMFD sp!, {r0-r3, r12, lr} // Restore the registers
|
||||
|
||||
/* This code 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. */
|
||||
|
||||
/* Enable interrupts. */
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSIE if // Enable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSIE i // Enable IRQ interrupts
|
||||
#endif
|
||||
|
||||
/* Wait for a thread to execute. */
|
||||
/* do */
|
||||
/* { */
|
||||
LDR r1, =_tx_thread_execute_ptr // Address of thread execute ptr
|
||||
|
||||
__tx_thread_schedule_loop:
|
||||
|
||||
LDR r0, [r1, #0] // Pickup next thread to execute
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_schedule_loop // If so, keep looking for a thread
|
||||
|
||||
/* } */
|
||||
/* while(_tx_thread_execute_ptr == TX_NULL); */
|
||||
|
||||
/* Yes! We have a thread to execute. Lockout interrupts and
|
||||
transfer control to it. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = _tx_thread_execute_ptr; */
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread
|
||||
STR r0, [r1, #0] // Setup current thread pointer
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_run_count++; */
|
||||
|
||||
LDR r2, [r0, #4] // Pickup run counter
|
||||
LDR r3, [r0, #24] // Pickup time-slice for this thread
|
||||
ADD r2, r2, #1 // Increment thread run-counter
|
||||
STR r2, [r0, #4] // Store the new run counter
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */
|
||||
|
||||
LDR r2, =_tx_timer_time_slice // Pickup address of time slice variable
|
||||
STR r3, [r2, #0] // Setup time-slice
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
|
||||
MOV r5, r0 // Save r0
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
MOV r0, r5 // Restore r0
|
||||
#endif
|
||||
|
||||
/* Determine if an interrupt frame or a synchronous task suspension frame is present. */
|
||||
CPS #SYS_MODE // Enter SYS mode
|
||||
LDR sp, [r0, #8] // Switch to thread stack pointer
|
||||
LDMIA sp!, {r4, r5} // Pickup the stack type and saved CPSR
|
||||
CPS #SVC_MODE // Enter SVC mode
|
||||
|
||||
/***************************************************************************/
|
||||
/* Set up MPU for module. */
|
||||
LDR r1, [r0, #0x94] // Pickup module instance pointer
|
||||
CMP r1, #0 // Valid module pointer?
|
||||
BEQ _tx_end_mpu_update // No - skip memory protection setup
|
||||
LDR r2, [r0, #0xA0] // Pickup tx_thread_module_user_mode
|
||||
CMP r2, #1 // In user mode?
|
||||
BNE _tx_end_mpu_update // No - skip memory protection setup
|
||||
/* Is the MPU already set up for this module? */
|
||||
/* Pickup the first data entry to check (txm_module_instance_mpu_registers[5]) */
|
||||
LDR r2, [r1, #0xA0] // Pickup txm_module_instance_mpu_registers[5]
|
||||
MOV r3, #5 // Select region 5
|
||||
MCR p15, 0, r3, c6, c2, 0 // Select region 5
|
||||
MRC p15, 0, r3, c6, c1, 0 // Read DRBAR into r3
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_end_mpu_update // Yes - skip memory protection setup
|
||||
|
||||
/* Disable MPU before applying new regions. */
|
||||
MRC p15, 0, r2, c1, c0, 0 // Read SCTLR
|
||||
BIC r2, r2, #1 // Disable MPU
|
||||
DSB
|
||||
MCR p15, 0, r2, c1, c0, 0 // Write to SCTLR
|
||||
ISB
|
||||
/* Loop to load MPU registers */
|
||||
MOV r3, #0 // Loop index
|
||||
ADD r1, r1, #0x64 // Build address of MPU register table
|
||||
_tx_mpu_loop:
|
||||
LDR r2, [r1] // Pickup txm_module_mpu_region_address
|
||||
MCR p15, 0, r3, c6, c2, 0 // Select region
|
||||
MCR p15, 0, r2, c6, c1, 0 // Write to DRBAR
|
||||
ADD r1, r1, #4 // Increment to next MPU parameter
|
||||
LDR r2, [r1] // Pickup txm_module_mpu_region_size
|
||||
MCR p15, 0, r2, c6, c1, 2 // Write to DRSR
|
||||
ADD r1, r1, #4 // Increment to next MPU parameter
|
||||
LDR r2, [r1] // Pickup txm_module_mpu_region_attributes
|
||||
MCR p15, 0, r2, c6, c1, 4 // Write to DRACR
|
||||
ADD r1, r1, #4 // Increment to next MPU parameter
|
||||
ADD r3, r3, #1 // Increment loop index
|
||||
CMP r3, #0xB // Check the limit
|
||||
BLE _tx_mpu_loop // Loop if not finished
|
||||
|
||||
/* Enable MPU with new regions. */
|
||||
MRC p15, 0, r2, c1, c0, 0 // Read SCTLR
|
||||
ORR r2, r2, #1 // Enable MPU
|
||||
ORR r2, r2, #0x20000 // Enable Background Region
|
||||
DSB
|
||||
MCR p15, 0, r2, c1, c0, 0 // Write to SCTLR
|
||||
ISB
|
||||
|
||||
_tx_end_mpu_update:
|
||||
/***************************************************************************/
|
||||
|
||||
CMP r4, #0 // Check for synchronous context switch
|
||||
BEQ _tx_solicited_return
|
||||
|
||||
MSR SPSR_cxsf, r5 // Setup SPSR for return
|
||||
LDR r1, [r0, #8] // Get thread SP
|
||||
LDR lr, [r1, #0x40] // Get thread PC
|
||||
CPS #SYS_MODE // Enter SYS mode
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r2, [r0, #144] // Pickup the VFP enabled flag
|
||||
CMP r2, #0 // Is the VFP enabled?
|
||||
BEQ _tx_skip_interrupt_vfp_restore // No, skip VFP interrupt restore
|
||||
VLDMIA sp!, {D0-D15} // Recover D0-D15
|
||||
LDR r4, [sp], #4 // Pickup FPSCR
|
||||
VMSR FPSCR, r4 // Restore FPSCR
|
||||
CPS #SVC_MODE // Enter SVC mode
|
||||
LDR lr, [r1, #0x144] // Get thread PC
|
||||
CPS #SYS_MODE // Enter SYS mode
|
||||
_tx_skip_interrupt_vfp_restore:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r0-r12, lr} // Restore registers
|
||||
ADD sp, sp, #4 // Fix stack pointer
|
||||
CPS #SVC_MODE // Enter SVC mode
|
||||
SUBS pc, lr, #0 // Return to point of thread interrupt
|
||||
|
||||
_tx_solicited_return:
|
||||
MOV r2, r5 // Move CPSR to scratch register
|
||||
CPS #SYS_MODE // Enter SYS mode
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r1, [r0, #144] // Pickup the VFP enabled flag
|
||||
CMP r1, #0 // Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_restore // No, skip VFP solicited restore
|
||||
VLDMIA sp!, {D8-D15} // Recover D8-D15
|
||||
LDR r4, [sp], #4 // Pickup FPSCR
|
||||
VMSR FPSCR, r4 // Restore FPSCR
|
||||
_tx_skip_solicited_vfp_restore:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r4-r11, lr} // Restore registers
|
||||
MOV r1, lr // Copy lr to r1 to preserve across mode change
|
||||
CPS #SVC_MODE // Enter SVC mode
|
||||
TST r1, #1 // Test LSB to see if we're returning to Thumb mode
|
||||
ORRNE r2, r2, #THUMB_MASK // If so, set Thumb bit
|
||||
BICEQ r2, r2, #THUMB_MASK // If not, clear Thumb bit
|
||||
MSR SPSR_cxsf, r2 // Recover CPSR
|
||||
MOV lr, r1 // Move r1 back to lr for a proper exception return
|
||||
SUBS pc, lr, #0 // Return to thread synchronously
|
||||
|
||||
/**************************************************************************/
|
||||
/* End __tx_svc_interrupt */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __ARM_FP
|
||||
.global tx_thread_vfp_enable
|
||||
.type tx_thread_vfp_enable, "function"
|
||||
tx_thread_vfp_enable:
|
||||
MRS r2, CPSR // Pickup the CPSR
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
CMP r1, #0 // Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_enable // If NULL, skip VFP enable
|
||||
MOV r0, #1 // Build enable value
|
||||
STR r0, [r1, #144] // Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_enable:
|
||||
MSR CPSR_cxsf, r2 // Recover CPSR
|
||||
BX LR // Return to caller
|
||||
|
||||
.global tx_thread_vfp_disable
|
||||
.type tx_thread_vfp_disable, "function"
|
||||
tx_thread_vfp_disable:
|
||||
MRS r2, CPSR // Pickup the CPSR
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
|
||||
LDR r1, [r0] // Pickup current thread pointer
|
||||
CMP r1, #0 // Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_disable // If NULL, skip VFP disable
|
||||
MOV r0, #0 // Build disable value
|
||||
STR r0, [r1, #144] // Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_disable:
|
||||
MSR CPSR_cxsf, r2 // Recover CPSR
|
||||
BX LR // Return to caller
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
#define SYS_MODE 0x1F // SYS mode
|
||||
#define THUMB_BIT 0x20 // Thumb-bit
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#define CPSR_MASK 0xDF // Mask initial CPSR, IRQ & FIQ ints enabled
|
||||
#else
|
||||
#define CPSR_MASK 0x9F // Mask initial CPSR, IRQ ints enabled
|
||||
#endif
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.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-R4 should look like the following after it is built:
|
||||
|
||||
Stack Top: 1 Interrupt stack frame type
|
||||
CPSR Initial value for CPSR
|
||||
a1 (r0) Initial value for a1
|
||||
a2 (r1) Initial value for a2
|
||||
a3 (r2) Initial value for a3
|
||||
a4 (r3) Initial value for a4
|
||||
v1 (r4) Initial value for v1
|
||||
v2 (r5) Initial value for v2
|
||||
v3 (r6) Initial value for v3
|
||||
v4 (r7) Initial value for v4
|
||||
v5 (r8) Initial value for v5
|
||||
sb (r9) Initial value for sb
|
||||
sl (r10) Initial value for sl
|
||||
fp (r11) Initial value for fp
|
||||
ip (r12) Initial value for ip
|
||||
lr (r14) Initial value for lr
|
||||
pc (r15) Initial value for pc
|
||||
0 For stack backtracing */
|
||||
|
||||
/* Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, #16] // Pickup end of stack area
|
||||
BIC r2, r2, #7 // Ensure 8-byte alignment
|
||||
SUB r2, r2, #76 // Allocate space for the stack frame
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, #1 // Build interrupt stack type
|
||||
STR r3, [r2, #0] // Store stack type
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #8] // Store initial r0
|
||||
STR r3, [r2, #12] // Store initial r1
|
||||
STR r3, [r2, #16] // Store initial r2
|
||||
STR r3, [r2, #20] // Store initial r3
|
||||
STR r3, [r2, #24] // Store initial r4
|
||||
STR r3, [r2, #28] // Store initial r5
|
||||
STR r3, [r2, #32] // Store initial r6
|
||||
STR r3, [r2, #36] // Store initial r7
|
||||
STR r3, [r2, #40] // Store initial r8
|
||||
STR r3, [r2, #44] // Store initial r9
|
||||
LDR r3, [r0, #12] // Pickup stack starting address
|
||||
STR r3, [r2, #48] // Store initial r10 (sl)
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #52] // Store initial r11
|
||||
STR r3, [r2, #56] // Store initial r12
|
||||
STR r3, [r2, #60] // Store initial lr
|
||||
STR r1, [r2, #64] // Store initial pc
|
||||
STR r3, [r2, #68] // 0 for back-trace
|
||||
|
||||
MRS r3, CPSR // Pickup CPSR
|
||||
BIC r3, r3, #CPSR_MASK // Mask mode bits of CPSR
|
||||
ORR r3, r3, #SYS_MODE // Build CPSR, SYS mode, interrupts enabled
|
||||
|
||||
TST r1, 1 // Test if Thumb bit is set in entry function address
|
||||
ITE NE
|
||||
ORRNE r3, r3, #THUMB_BIT // Yes, set the Thumb bit
|
||||
BICEQ r3, r3, #THUMB_BIT // No, clear the Thumb bit
|
||||
STR r3, [r2, #4] // Store initial CPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
/* thread_ptr -> tx_thread_stack_ptr = r2; */
|
||||
|
||||
STR r2, [r0, #8] // Save stack pointer in thread's
|
||||
// control block
|
||||
BX lr // Return to caller
|
||||
/* } */
|
||||
@@ -0,0 +1,162 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_thread_schedule
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_thread_exit
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_system_return(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_system_return
|
||||
.type _tx_thread_system_return, "function"
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Save minimal context on the stack. */
|
||||
|
||||
STMDB sp!, {r4-r11, lr} // Save minimal context
|
||||
LDR r5, =_tx_thread_current_ptr // Pickup address of current ptr
|
||||
LDR r6, [r5, #0] // Pickup current thread pointer
|
||||
|
||||
#ifdef __ARM_FP
|
||||
LDR r0, [r6, #144] // Pickup the VFP enabled flag
|
||||
CMP r0, #0 // Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_save // No, skip VFP solicited save
|
||||
VMRS r4, FPSCR // Pickup the FPSCR
|
||||
STR r4, [sp, #-4]! // Save FPSCR
|
||||
VSTMDB sp!, {D8-D15} // Save D8-D15
|
||||
_tx_skip_solicited_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r0, #0 // Build a solicited stack type
|
||||
MRS r1, CPSR // Pickup the CPSR
|
||||
STMDB sp!, {r0-r1} // Save type and CPSR
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i // Disable IRQ interrupts
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
#endif
|
||||
LDR r2, =_tx_timer_time_slice // Pickup address of time slice
|
||||
LDR r1, [r2, #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; */
|
||||
|
||||
STR sp, [r6, #8] // Save thread stack pointer
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
/* if (_tx_timer_time_slice) */
|
||||
/* { */
|
||||
|
||||
MOV r4, #0 // Build clear value
|
||||
CMP r1, #0 // Is a time-slice active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save the time-slice
|
||||
|
||||
/* Save the current remaining time-slice. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; */
|
||||
/* _tx_timer_time_slice = 0; */
|
||||
|
||||
STR r4, [r2, #0] // Clear time-slice
|
||||
STR r1, [r6, #24] // Store current time-slice
|
||||
|
||||
/* } */
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
STR r4, [r5, #0] // Clear current thread pointer
|
||||
|
||||
B _tx_thread_schedule // Jump to scheduler!
|
||||
|
||||
/* } */
|
||||
@@ -0,0 +1,193 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h" */
|
||||
/* #include "tx_thread.h" */
|
||||
|
||||
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
.global _tx_execution_isr_enter
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_vectored_context_save Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_vectored_context_save(VOID) */
|
||||
/* { */
|
||||
.global _tx_thread_vectored_context_save
|
||||
.type _tx_thread_vectored_context_save, "function"
|
||||
_tx_thread_vectored_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, and all registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++) */
|
||||
/* { */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if // Disable IRQ and FIQ interrupts
|
||||
#endif
|
||||
LDR r3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR r2, [r3, #0] // Pickup system state
|
||||
CMP r2, #0 // Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save // Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3, #0] // Store it back in the variable
|
||||
|
||||
/* Note: Minimal context of interrupted thread is already saved. */
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
BX lr // Return to caller
|
||||
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr) */
|
||||
/* { */
|
||||
|
||||
ADD r2, r2, #1 // Increment the interrupt counter
|
||||
STR r2, [r3, #0] // Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] // Pickup current thread pointer
|
||||
CMP r0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save // If so, interrupt occurred in
|
||||
// scheduling loop - nothing needs saving!
|
||||
|
||||
/* Note: Minimal context of interrupted thread is already saved. */
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
BX lr // 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. */
|
||||
|
||||
MOV r10, #0 // Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} // Save ISR lr
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
POP {lr} // Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #32 // Recover saved registers
|
||||
|
||||
BX lr // Return to caller
|
||||
|
||||
/* } */
|
||||
/* } */
|
||||
@@ -0,0 +1,257 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
/* Define Assembly language external references... */
|
||||
|
||||
.global _tx_timer_time_slice
|
||||
.global _tx_timer_system_clock
|
||||
.global _tx_timer_current_ptr
|
||||
.global _tx_timer_list_start
|
||||
.global _tx_timer_list_end
|
||||
.global _tx_timer_expired_time_slice
|
||||
.global _tx_timer_expired
|
||||
.global _tx_thread_time_slice
|
||||
.global _tx_timer_expiration_process
|
||||
|
||||
|
||||
#ifdef TX_THUMB_MODE
|
||||
.thumb
|
||||
#else
|
||||
.arm
|
||||
#endif
|
||||
.text
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Cortex-R4/AC6 */
|
||||
/* 6.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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_timer_interrupt(VOID) */
|
||||
/* { */
|
||||
.global _tx_timer_interrupt
|
||||
.type _tx_timer_interrupt, "function"
|
||||
_tx_timer_interrupt:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that context save has already
|
||||
been called, and therefore the compiler scratch registers are available
|
||||
for use. */
|
||||
|
||||
/* Increment the system clock. */
|
||||
/* _tx_timer_system_clock++; */
|
||||
|
||||
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
|
||||
LDR r0, [r1, #0] // Pickup system clock
|
||||
ADD r0, r0, #1 // Increment system clock
|
||||
STR r0, [r1, #0] // Store new system clock
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
/* if (_tx_timer_time_slice) */
|
||||
/* { */
|
||||
|
||||
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
|
||||
LDR r2, [r3, #0] // Pickup time-slice
|
||||
CMP r2, #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 r2, r2, #1 // Decrement the time-slice
|
||||
STR r2, [r3, #0] // Store new time-slice value
|
||||
|
||||
/* Check for expiration. */
|
||||
/* if (__tx_timer_time_slice == 0) */
|
||||
|
||||
CMP r2, #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 r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
|
||||
MOV r0, #1 // Build expired value
|
||||
STR r0, [r3, #0] // Set time-slice expiration flag
|
||||
|
||||
/* } */
|
||||
|
||||
__tx_timer_no_time_slice:
|
||||
|
||||
/* Test for timer expiration. */
|
||||
/* if (*_tx_timer_current_ptr) */
|
||||
/* { */
|
||||
|
||||
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer addr
|
||||
LDR r0, [r1, #0] // Pickup current timer
|
||||
LDR r2, [r0, #0] // Pickup timer list entry
|
||||
CMP r2, #0 // Is there anything in the list?
|
||||
BEQ __tx_timer_no_timer // No, just increment the timer
|
||||
|
||||
/* Set expiration flag. */
|
||||
/* _tx_timer_expired = TX_TRUE; */
|
||||
|
||||
LDR r3, =_tx_timer_expired // Pickup expiration flag address
|
||||
MOV r2, #1 // Build expired value
|
||||
STR r2, [r3, #0] // Set expired flag
|
||||
B __tx_timer_done // Finished timer processing
|
||||
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
__tx_timer_no_timer:
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
/* _tx_timer_current_ptr++; */
|
||||
|
||||
ADD r0, r0, #4 // Move to next timer
|
||||
|
||||
/* Check for wrap-around. */
|
||||
/* if (_tx_timer_current_ptr == _tx_timer_list_end) */
|
||||
|
||||
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
|
||||
LDR r2, [r3, #0] // Pickup list end
|
||||
CMP r0, r2 // Are we at list end?
|
||||
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
/* _tx_timer_current_ptr = _tx_timer_list_start; */
|
||||
|
||||
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
|
||||
LDR r0, [r3, #0] // Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR r0, [r1, #0] // Store new current timer pointer
|
||||
/* } */
|
||||
|
||||
__tx_timer_done:
|
||||
|
||||
|
||||
/* See if anything has expired. */
|
||||
/* if ((_tx_timer_expired_time_slice) (_tx_timer_expired)) */
|
||||
/* { */
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
|
||||
LDR r2, [r3, #0] // Pickup time-slice expired flag
|
||||
CMP r2, #0 // Did a time-slice expire?
|
||||
BNE __tx_something_expired // If non-zero, time-slice expired
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CMP r0, #0 // Did a timer expire?
|
||||
BEQ __tx_timer_nothing_expired // No, nothing expired
|
||||
|
||||
__tx_something_expired:
|
||||
|
||||
|
||||
STMDB sp!, {r0, lr} // Save the lr register on the stack
|
||||
// and save r0 just to keep 8-byte alignment
|
||||
|
||||
/* Did a timer expire? */
|
||||
/* if (_tx_timer_expired) */
|
||||
/* { */
|
||||
|
||||
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
|
||||
LDR r0, [r1, #0] // Pickup timer expired flag
|
||||
CMP r0, #0 // Check for timer expiration
|
||||
BEQ __tx_timer_dont_activate // If not set, skip timer activation
|
||||
|
||||
/* Process timer expiration. */
|
||||
/* _tx_timer_expiration_process(); */
|
||||
|
||||
BL _tx_timer_expiration_process // Call the timer expiration handling routine
|
||||
|
||||
/* } */
|
||||
__tx_timer_dont_activate:
|
||||
|
||||
/* Did time slice expire? */
|
||||
/* if (_tx_timer_expired_time_slice) */
|
||||
/* { */
|
||||
|
||||
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
|
||||
LDR r2, [r3, #0] // Pickup the actual flag
|
||||
CMP r2, #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:
|
||||
|
||||
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
|
||||
// the 8-byte stack alignment
|
||||
|
||||
/* } */
|
||||
|
||||
__tx_timer_nothing_expired:
|
||||
BX lr // Return to caller
|
||||
|
||||
/* } */
|
||||
@@ -0,0 +1,189 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_power_of_two_block_size Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates a power of two size at or immediately above*/
|
||||
/* the input size and returns it to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* size Block size */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* calculated size Rounded up to power of two */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_alignment_adjust Adjust alignment for Cortex-R */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_power_of_two_block_size(ULONG size)
|
||||
{
|
||||
/* Check for 0 size. */
|
||||
if(size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Minimum MPU block size is 32. */
|
||||
if(size <= 32)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
/* Bit twiddling trick to round to next high power of 2
|
||||
(if original size is power of 2, it will return original size. Perfect!) */
|
||||
size--;
|
||||
size |= size >> 1;
|
||||
size |= size >> 2;
|
||||
size |= size >> 4;
|
||||
size |= size >> 8;
|
||||
size |= size >> 16;
|
||||
size++;
|
||||
|
||||
/* Return a power of 2 size at or above the input size. */
|
||||
return(size);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_alignment_adjust Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function adjusts the alignment and size of the code and data */
|
||||
/* section for a given module implementation. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_preamble Pointer to module preamble */
|
||||
/* code_size Size of the code area (updated) */
|
||||
/* code_alignment Code area alignment (updated) */
|
||||
/* data_size Size of data area (updated) */
|
||||
/* data_alignment Data area alignment (updated) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_power_of_two_block_size Calculate power of two size */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble,
|
||||
ULONG *code_size,
|
||||
ULONG *code_alignment,
|
||||
ULONG *data_size,
|
||||
ULONG *data_alignment)
|
||||
{
|
||||
|
||||
ULONG local_code_size;
|
||||
ULONG local_code_alignment;
|
||||
ULONG local_data_size;
|
||||
ULONG local_data_alignment;
|
||||
ULONG code_size_accum;
|
||||
ULONG data_size_accum;
|
||||
|
||||
/* Copy the input parameters into local variables for ease of use. */
|
||||
local_code_size = *code_size;
|
||||
local_code_alignment = *code_alignment;
|
||||
local_data_size = *data_size;
|
||||
local_data_alignment = *data_alignment;
|
||||
|
||||
/* Determine code block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU code entries available. The following is how the code size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
local_code_alignment = _txm_power_of_two_block_size(local_code_size) >> 2;
|
||||
code_size_accum = local_code_alignment + local_code_alignment;
|
||||
code_size_accum = code_size_accum + (_txm_power_of_two_block_size(local_code_size - code_size_accum) >> 1);
|
||||
code_size_accum = code_size_accum + _txm_power_of_two_block_size(local_code_size - code_size_accum);
|
||||
local_code_size = code_size_accum;
|
||||
|
||||
/* Determine data block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU data entries available. The following is how the data size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
local_data_alignment = _txm_power_of_two_block_size(local_data_size) >> 2;
|
||||
data_size_accum = local_data_alignment + local_data_alignment;
|
||||
data_size_accum = data_size_accum + (_txm_power_of_two_block_size(local_data_size - data_size_accum) >> 1);
|
||||
data_size_accum = data_size_accum + _txm_power_of_two_block_size(local_data_size - data_size_accum);
|
||||
local_data_size = data_size_accum;
|
||||
|
||||
/* Return all the information to the caller. */
|
||||
*code_size = local_code_size;
|
||||
*code_alignment = local_code_alignment;
|
||||
*data_size = local_data_size;
|
||||
*data_alignment = local_data_alignment;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_mutex.h"
|
||||
#include "tx_queue.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_external_memory_enable Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function adds an entry in the MPU table for a shared */
|
||||
/* memory space. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module instance pointer */
|
||||
/* start_address Start address of memory */
|
||||
/* length Length of external memory */
|
||||
/* attributes Memory attributes (r/w) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_mutex_get Get protection mutex */
|
||||
/* _tx_mutex_put Release protection mutex */
|
||||
/* _txm_power_of_two_block_size Round length to power of two */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_external_memory_enable(TXM_MODULE_INSTANCE *module_instance,
|
||||
VOID *start_address,
|
||||
ULONG length,
|
||||
UINT attributes)
|
||||
{
|
||||
|
||||
ULONG block_size;
|
||||
ULONG region_size;
|
||||
ULONG srd_bits;
|
||||
ULONG size_register;
|
||||
ULONG address;
|
||||
ULONG shared_index;
|
||||
ULONG attributes_check = 0;
|
||||
|
||||
/* Determine if the module manager has been initialized. */
|
||||
if (_txm_module_manager_ready != TX_TRUE)
|
||||
{
|
||||
/* Module manager has not been initialized. */
|
||||
return(TX_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
/* Determine if the module is valid. */
|
||||
if (module_instance == TX_NULL)
|
||||
{
|
||||
/* Invalid module pointer. */
|
||||
return(TX_PTR_ERROR);
|
||||
}
|
||||
|
||||
/* Get module manager protection mutex. */
|
||||
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
|
||||
|
||||
/* Determine if the module instance is valid. */
|
||||
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid module pointer. */
|
||||
return(TX_PTR_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if the module instance is in the loaded state. */
|
||||
if (module_instance -> txm_module_instance_state != TXM_MODULE_LOADED)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return error if the module is not ready. */
|
||||
return(TX_START_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if there are shared memory entries available. */
|
||||
if(module_instance -> txm_module_instance_shared_memory_count >= TXM_MODULE_MPU_SHARED_ENTRIES)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* No more entries available. */
|
||||
return(TX_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Start address and length must adhere to Cortex-R MPU.
|
||||
The address must align with the block size. */
|
||||
|
||||
block_size = _txm_power_of_two_block_size(length);
|
||||
address = (ULONG) start_address;
|
||||
if(address != (address & ~(block_size - 1)))
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return alignment error. */
|
||||
return(TXM_MODULE_ALIGNMENT_ERROR);
|
||||
}
|
||||
|
||||
/* At this point, we have a valid address and block size.
|
||||
Set up MPU registers. */
|
||||
|
||||
/* Generate index into shared memory entries. */
|
||||
shared_index = TXM_MODULE_MPU_SHARED_INDEX + module_instance -> txm_module_instance_shared_memory_count;
|
||||
|
||||
/* Save address register. */
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_address = address;
|
||||
|
||||
/* Calculate the region size. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
/* Calculate the subregion bits. */
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, length);
|
||||
|
||||
/* Save size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_size = size_register;
|
||||
|
||||
/* Check for optional attributes. */
|
||||
if(attributes & TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE)
|
||||
{
|
||||
attributes_check = TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT;
|
||||
}
|
||||
|
||||
/* Save attributes register. */
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_attributes = attributes_check | TXM_MODULE_MPU_SHARED_ACCESS_CONTROL;
|
||||
|
||||
/* Keep track of shared memory address and length in module instance. */
|
||||
module_instance -> txm_module_instance_shared_memory_address[module_instance -> txm_module_instance_shared_memory_count] = address;
|
||||
module_instance -> txm_module_instance_shared_memory_length[module_instance -> txm_module_instance_shared_memory_count] = length;
|
||||
|
||||
/* Increment counter. */
|
||||
module_instance -> txm_module_instance_shared_memory_count++;
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
@@ -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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define the user's fault notification callback function pointer. This is
|
||||
setup via the txm_module_manager_memory_fault_notify API. */
|
||||
|
||||
VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
|
||||
|
||||
|
||||
/* Define a macro that can be used to allocate global variables useful to
|
||||
store information about the last fault. This macro is defined in
|
||||
txm_module_port.h and is usually populated in the assembly language
|
||||
fault handling prior to the code calling _txm_module_manager_memory_fault_handler. */
|
||||
|
||||
TXM_MODULE_MANAGER_FAULT_INFO
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_memory_fault_handler Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function handles a fault associated with a memory protected */
|
||||
/* module. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_terminate Terminate thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Fault handler */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_memory_fault_handler(VOID)
|
||||
{
|
||||
|
||||
TXM_MODULE_INSTANCE *module_instance_ptr;
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Pickup the current thread. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Initialize the module instance pointer to NULL. */
|
||||
module_instance_ptr = TX_NULL;
|
||||
|
||||
/* Is there a thread? */
|
||||
if (thread_ptr)
|
||||
{
|
||||
/* Pickup the module instance. */
|
||||
module_instance_ptr = thread_ptr -> tx_thread_module_instance_ptr;
|
||||
|
||||
/* Terminate the current thread. */
|
||||
_tx_thread_terminate(_tx_thread_current_ptr);
|
||||
}
|
||||
|
||||
/* Determine if there is a user memory fault notification callback. */
|
||||
if (_txm_module_manager_fault_notify)
|
||||
{
|
||||
/* Yes, call the user's notification memory fault callback. */
|
||||
(_txm_module_manager_fault_notify)(thread_ptr, module_instance_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define the external user's fault notification callback function pointer. This is
|
||||
setup via the txm_module_manager_memory_fault_notify API. */
|
||||
|
||||
extern VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_memory_fault_notify Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application callback when/if a memory */
|
||||
/* fault occurs. The supplied thread is automatically terminated, but */
|
||||
/* any other threads in the same module may still execute. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* notify_function Memory fault notification */
|
||||
/* function, NULL disables. */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
{
|
||||
/* Setup notification function. */
|
||||
_txm_module_manager_fault_notify = notify_function;
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,547 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_region_size_get Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function converts the region size in bytes to the block size */
|
||||
/* for the Cortex-R4 MPU specification. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* block_size Size of the block in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* MPU size specification */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_module_manager_region_size_get(ULONG block_size)
|
||||
{
|
||||
|
||||
ULONG return_value;
|
||||
|
||||
|
||||
/* Process relative to the input block size. */
|
||||
if (block_size == 32)
|
||||
{
|
||||
return_value = 0x04;
|
||||
}
|
||||
else if (block_size == 64)
|
||||
{
|
||||
return_value = 0x05;
|
||||
}
|
||||
else if (block_size == 128)
|
||||
{
|
||||
return_value = 0x06;
|
||||
}
|
||||
else if (block_size == 256)
|
||||
{
|
||||
return_value = 0x07;
|
||||
}
|
||||
else if (block_size == 512)
|
||||
{
|
||||
return_value = 0x08;
|
||||
}
|
||||
else if (block_size == 1024)
|
||||
{
|
||||
return_value = 0x09;
|
||||
}
|
||||
else if (block_size == 2048)
|
||||
{
|
||||
return_value = 0x0A;
|
||||
}
|
||||
else if (block_size == 4096)
|
||||
{
|
||||
return_value = 0x0B;
|
||||
}
|
||||
else if (block_size == 8192)
|
||||
{
|
||||
return_value = 0x0C;
|
||||
}
|
||||
else if (block_size == 16384)
|
||||
{
|
||||
return_value = 0x0D;
|
||||
}
|
||||
else if (block_size == 32768)
|
||||
{
|
||||
return_value = 0x0E;
|
||||
}
|
||||
else if (block_size == 65536)
|
||||
{
|
||||
return_value = 0x0F;
|
||||
}
|
||||
else if (block_size == 131072)
|
||||
{
|
||||
return_value = 0x10;
|
||||
}
|
||||
else if (block_size == 262144)
|
||||
{
|
||||
return_value = 0x11;
|
||||
}
|
||||
else if (block_size == 524288)
|
||||
{
|
||||
return_value = 0x12;
|
||||
}
|
||||
else if (block_size == 1048576)
|
||||
{
|
||||
return_value = 0x13;
|
||||
}
|
||||
else if (block_size == 2097152)
|
||||
{
|
||||
return_value = 0x14;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Max 4MB MPU pages for modules. */
|
||||
return_value = 0x15;
|
||||
}
|
||||
|
||||
return(return_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_calculate_srd_bits Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates the SRD bits that need to be set to */
|
||||
/* protect "length" bytes in a block. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* block_size Size of the block in bytes */
|
||||
/* length Actual length in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* SRD bits to be OR'ed with region attribute register. */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length)
|
||||
{
|
||||
|
||||
ULONG srd_bits = 0;
|
||||
UINT srd_bit_index;
|
||||
|
||||
/* length is smaller than block_size, set SRD bits if block_size is 256 or more. */
|
||||
if((block_size >= 256) && (length < block_size))
|
||||
{
|
||||
/* Divide block_size by 8 by shifting right 3. Result is size of subregion. */
|
||||
block_size = block_size >> 3;
|
||||
|
||||
/* Set SRD index into attribute register. */
|
||||
srd_bit_index = 8;
|
||||
|
||||
/* If subregion overlaps length, move to the next subregion. */
|
||||
while(length > block_size)
|
||||
{
|
||||
length = length - block_size;
|
||||
srd_bit_index++;
|
||||
}
|
||||
|
||||
/* Check for a portion of code remaining. */
|
||||
if(length)
|
||||
{
|
||||
srd_bit_index++;
|
||||
}
|
||||
|
||||
/* Set unused subregion bits. */
|
||||
while(srd_bit_index < 16)
|
||||
{
|
||||
srd_bits = srd_bits | (0x1 << srd_bit_index);
|
||||
srd_bit_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return(srd_bits);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets up the MPU register definitions based on the */
|
||||
/* module's memory characteristics. */
|
||||
/* MPU layout for the Cortex-R4: */
|
||||
/* Entry Description */
|
||||
/* 0 Kernel mode entry */
|
||||
/* 1 Module code region */
|
||||
/* 2 Module code region */
|
||||
/* 3 Module code region */
|
||||
/* 4 Module code region */
|
||||
/* 5 Module data region */
|
||||
/* 6 Module data region */
|
||||
/* 7 Module data region */
|
||||
/* 8 Module data region */
|
||||
/* 9 Module shared memory region */
|
||||
/* 10 Module shared memory region */
|
||||
/* 11 Module shared memory region */
|
||||
/* */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Pointer to module instance */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* MPU specifications for module in module_instance */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_region_size_get */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_create */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance)
|
||||
{
|
||||
|
||||
ULONG code_address;
|
||||
ULONG code_size;
|
||||
ULONG data_address;
|
||||
ULONG data_size;
|
||||
ULONG start_stop_stack_size;
|
||||
ULONG callback_stack_size;
|
||||
ULONG block_size;
|
||||
ULONG base_address_register;
|
||||
ULONG size_register;
|
||||
ULONG region_size;
|
||||
ULONG srd_bits = 0;
|
||||
UINT mpu_table_index;
|
||||
UINT i;
|
||||
|
||||
|
||||
/* Setup the first region for kernel mode entry. */
|
||||
|
||||
/* Set address register to user mode entry function address, which is guaranteed to be at least 32-byte aligned. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_address = (ULONG) _txm_module_manager_user_mode_entry;
|
||||
|
||||
/* Set the size (32 bytes) and enable bit. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_size = (_txm_module_manager_region_size_get(32) << 1) | TXM_ENABLE_REGION;
|
||||
|
||||
/* Set attributes. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_attributes = TXM_MODULE_MPU_CODE_ACCESS_CONTROL;
|
||||
|
||||
/* End of kernel mode entry setup. */
|
||||
|
||||
/* Setup code protection. */
|
||||
|
||||
/* Initialize the MPU table index. */
|
||||
mpu_table_index = 1;
|
||||
|
||||
/* Pickup code starting address and actual size. */
|
||||
code_address = (ULONG) module_instance -> txm_module_instance_code_start;
|
||||
code_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_code_size;
|
||||
|
||||
/* Determine code block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU code entries available. The following is how the code size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
|
||||
/* Now loop through to setup MPU protection for the code area. */
|
||||
for (i = 0; i < TXM_MODULE_MPU_CODE_ENTRIES; i++)
|
||||
{
|
||||
/* First two MPU blocks are 1/4 of the largest power of two
|
||||
that is greater than or equal to code size. */
|
||||
if (i < 2)
|
||||
{
|
||||
block_size = _txm_power_of_two_block_size(code_size) >> 2;
|
||||
}
|
||||
|
||||
/* Third MPU block is the largest power of 2 that fits in the remaining space. */
|
||||
else if (i == 2)
|
||||
{
|
||||
/* Subtract (block_size*2) from code_size to calculate remaining space. */
|
||||
code_size = code_size - (block_size << 1);
|
||||
block_size = _txm_power_of_two_block_size(code_size) >> 1;
|
||||
}
|
||||
|
||||
/* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
else
|
||||
{
|
||||
/* Calculate remaining space. */
|
||||
code_size = code_size - block_size;
|
||||
block_size = _txm_power_of_two_block_size(code_size);
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, code_size);
|
||||
}
|
||||
|
||||
/* Build the base address register. */
|
||||
base_address_register = (code_address & ~(block_size - 1));
|
||||
|
||||
/* Calculate the region size information. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
|
||||
/* Build the size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
|
||||
/* Setup the MPU address, size, and attribute registers. */
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = base_address_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_size = size_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attributes = TXM_MODULE_MPU_CODE_ACCESS_CONTROL;
|
||||
|
||||
/* Adjust the code address. */
|
||||
code_address = code_address + block_size;
|
||||
|
||||
/* Increment MPU table index. */
|
||||
mpu_table_index++;
|
||||
}
|
||||
/* End of code protection. */
|
||||
|
||||
/* Setup data protection. */
|
||||
|
||||
/* Reset SRD bitfield. */
|
||||
srd_bits = 0;
|
||||
|
||||
/* Pickup data starting address and actual size. */
|
||||
data_address = (ULONG) module_instance -> txm_module_instance_data_start;
|
||||
|
||||
/* Adjust the size of the module elements to be aligned to the default alignment. We do this
|
||||
so that when we partition the allocated memory, we can simply place these regions right beside
|
||||
each other without having to align their pointers. Note this only works when they all have
|
||||
the same alignment. */
|
||||
|
||||
data_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_data_size;
|
||||
start_stop_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_start_stop_stack_size;
|
||||
callback_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_callback_stack_size;
|
||||
|
||||
data_size = ((data_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
start_stop_stack_size = ((start_stop_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
callback_stack_size = ((callback_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
/* Update the data size to include thread stacks. */
|
||||
data_size = data_size + start_stop_stack_size + callback_stack_size;
|
||||
|
||||
|
||||
/* Determine data block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU data entries available. The following is how the data size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
|
||||
/* Now loop through to setup MPU protection for the data area. */
|
||||
for (i = 0; i < TXM_MODULE_MPU_DATA_ENTRIES; i++)
|
||||
{
|
||||
/* First two MPU blocks are 1/4 of the largest power of two
|
||||
that is greater than or equal to data size. */
|
||||
if (i < 2)
|
||||
{
|
||||
block_size = _txm_power_of_two_block_size(data_size) >> 2;
|
||||
}
|
||||
|
||||
/* Third MPU block is the largest power of 2 that fits in the remaining space. */
|
||||
else if (i == 2)
|
||||
{
|
||||
/* Subtract (block_size*2) from data_size to calculate remaining space. */
|
||||
data_size = data_size - (block_size << 1);
|
||||
block_size = _txm_power_of_two_block_size(data_size) >> 1;
|
||||
}
|
||||
|
||||
/* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
else
|
||||
{
|
||||
/* Calculate remaining space. */
|
||||
data_size = data_size - block_size;
|
||||
block_size = _txm_power_of_two_block_size(data_size);
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, data_size);
|
||||
}
|
||||
|
||||
/* Build the base address register. */
|
||||
base_address_register = (data_address & ~(block_size - 1));
|
||||
|
||||
/* Calculate the region size information. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
|
||||
/* Build the size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
|
||||
/* Setup the MPU address, size, and attribute registers. */
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = base_address_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_size = size_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attributes = TXM_MODULE_MPU_DATA_ACCESS_CONTROL;
|
||||
|
||||
/* Adjust the data address. */
|
||||
data_address = data_address + block_size;
|
||||
|
||||
/* Increment MPU table index. */
|
||||
mpu_table_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_inside_data_check Cortex-R4/MPU/ARM */
|
||||
/* 6.1.6 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function checks if the specified object is inside shared */
|
||||
/* memory. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Pointer to module instance */
|
||||
/* obj_ptr Pointer to the object */
|
||||
/* obj_size Size of the object */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Whether the object is inside the shared memory region. */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* N/A */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Module dispatch check functions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 04-02-2021 Scott Larson Modified comments, added */
|
||||
/* check for overflow, */
|
||||
/* resulting in version 6.1.6 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size)
|
||||
{
|
||||
|
||||
UINT shared_memory_index;
|
||||
UINT num_shared_memory_mpu_entries;
|
||||
ALIGN_TYPE shared_memory_address_start;
|
||||
ALIGN_TYPE shared_memory_address_end;
|
||||
|
||||
/* Check for overflow. */
|
||||
if ((obj_ptr) > ((obj_ptr) + (obj_size)))
|
||||
{
|
||||
return(TX_FALSE);
|
||||
}
|
||||
|
||||
/* Check if the object is inside the module data. */
|
||||
if ((obj_ptr >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) &&
|
||||
((obj_ptr + obj_size) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1)))
|
||||
{
|
||||
return(TX_TRUE);
|
||||
}
|
||||
|
||||
/* Check if the object is inside the shared memory. */
|
||||
num_shared_memory_mpu_entries = module_instance -> txm_module_instance_shared_memory_count;
|
||||
for (shared_memory_index = 0; shared_memory_index < num_shared_memory_mpu_entries; shared_memory_index++)
|
||||
{
|
||||
|
||||
shared_memory_address_start = (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address[shared_memory_index];
|
||||
shared_memory_address_end = shared_memory_address_start + module_instance -> txm_module_instance_shared_memory_length[shared_memory_index];
|
||||
|
||||
if ((obj_ptr >= (ALIGN_TYPE) shared_memory_address_start) &&
|
||||
((obj_ptr + obj_size) <= (ALIGN_TYPE) shared_memory_address_end))
|
||||
{
|
||||
return(TX_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(TX_FALSE);
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define THUMB_MASK 0x20 // THUMB bit
|
||||
#define USR_MODE 0x10 // USR mode
|
||||
#define SYS_MODE 0x1F // SYS mode
|
||||
#define CPSR_MASK 0xBF // Mask initial CPSR, IRQ ints enabled
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_stack_build Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
{ */
|
||||
.text
|
||||
.global _txm_module_manager_thread_stack_build
|
||||
.type _txm_module_manager_thread_stack_build, "function"
|
||||
_txm_module_manager_thread_stack_build:
|
||||
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the Cortex-R4 should look like the following after it is built:
|
||||
|
||||
Stack Top: 1 Interrupt stack frame type
|
||||
CPSR Initial value for CPSR
|
||||
r0 Initial value for r0
|
||||
r1 Initial value for r1
|
||||
r2 Initial value for r2
|
||||
r3 Initial value for r3
|
||||
r4 Initial value for r4
|
||||
r5 Initial value for r5
|
||||
r6 Initial value for r6
|
||||
r7 Initial value for r7
|
||||
r8 Initial value for r8
|
||||
r9 Initial value for r9
|
||||
r10 Initial value for r10
|
||||
r11 Initial value for r11
|
||||
r12 Initial value for r12
|
||||
lr Initial value for lr (r14)
|
||||
pc Initial value for pc (r15)
|
||||
0 For stack backtracing
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, #16] // Pickup end of stack area
|
||||
BIC r2, r2, #7 // Ensure 8-byte alignment
|
||||
SUB r2, r2, #76 // Allocate space for the stack frame
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, #1 // Build interrupt stack type
|
||||
STR r3, [r2, #0] // Store stack type
|
||||
STR r0, [r2, #8] // Store initial r0 (thread pointer)
|
||||
LDR r3, [r0, #8] // Pickup thread info pointer (it's in the stack pointer location right now)
|
||||
STR r3, [r2, #12] // Store initial r1
|
||||
LDR r3, [r3, #8] // Pickup data base register
|
||||
STR r3, [r2, #44] // Store initial r9
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #16] // Store initial r2
|
||||
STR r3, [r2, #20] // Store initial r3
|
||||
STR r3, [r2, #24] // Store initial r4
|
||||
STR r3, [r2, #28] // Store initial r5
|
||||
STR r3, [r2, #32] // Store initial r6
|
||||
STR r3, [r2, #36] // Store initial r7
|
||||
STR r3, [r2, #40] // Store initial r8
|
||||
LDR r3, [r0, #12] // Pickup stack starting address
|
||||
STR r3, [r2, #48] // Store initial r10 (sl)
|
||||
MOV r3, #0 // Build initial register value
|
||||
STR r3, [r2, #52] // Store initial r11
|
||||
STR r3, [r2, #56] // Store initial r12
|
||||
STR r3, [r2, #60] // Store initial lr
|
||||
STR r1, [r2, #64] // Store initial pc
|
||||
STR r3, [r2, #68] // 0 for back-trace
|
||||
MRS r3, CPSR // Pickup CPSR
|
||||
BIC r3, r3, #CPSR_MASK // Mask mode bits of CPSR
|
||||
TST r1, #1 // Test if THUMB bit set in initial PC
|
||||
ORRNE r3, r3, #THUMB_MASK // Set T bit if set
|
||||
LDR r1, [r0, #156] // Load tx_thread_module_user_mode
|
||||
TST r1, #1 // Test if the user mode flag is set
|
||||
ORREQ r3, r3, #SYS_MODE // Flag not set: Build CPSR, SYS mode, IRQ enabled
|
||||
ORRNE r3, r3, #USR_MODE // Flag set: Build CPSR, USR mode, IRQ enabled
|
||||
STR r3, [r2, #4] // Store initial CPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
/* thread_ptr -> tx_thread_stack_ptr = r2; */
|
||||
|
||||
STR r2, [r0, #8] // Save stack pointer in thread's control block
|
||||
BX lr // Return to caller
|
||||
/* } */
|
||||
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.global _txm_module_manager_kernel_dispatch
|
||||
.global _txm_system_mode_enter
|
||||
.global _txm_system_mode_exit
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_user_mode_entry Cortex-R4/MPU/ARM */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function allows modules to enter kernel mode. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* SVC 1 Enter kernel mode */
|
||||
/* SVC 2 Exit kernel mode */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Modules in user mode */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.text
|
||||
.align 12
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
.global _txm_module_manager_user_mode_entry
|
||||
.type _txm_module_manager_user_mode_entry, "function"
|
||||
_txm_module_manager_user_mode_entry:
|
||||
_txm_system_mode_enter:
|
||||
SVC 1 // Get out of user mode.
|
||||
_txm_module_priv:
|
||||
/* At this point, we are in system mode.
|
||||
Save LR (and r3 for 8 byte aligned stack) and call the kernel dispatch function. */
|
||||
PUSH {r3, lr}
|
||||
BL _txm_module_manager_kernel_dispatch
|
||||
POP {r3, lr}
|
||||
|
||||
_txm_system_mode_exit:
|
||||
/* Trap to restore user mode while inside of ThreadX. */
|
||||
SVC 2
|
||||
|
||||
BX lr // Return to the caller.
|
||||
NOP
|
||||
NOP
|
||||
19
ports_module/cortex_r4/iar/example_build/azure_rtos.eww
Normal file
19
ports_module/cortex_r4/iar/example_build/azure_rtos.eww
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<workspace>
|
||||
<project>
|
||||
<path>$WS_DIR$\sample_threadx.ewp</path>
|
||||
</project>
|
||||
<project>
|
||||
<path>$WS_DIR$\sample_threadx_module.ewp</path>
|
||||
</project>
|
||||
<project>
|
||||
<path>$WS_DIR$\sample_threadx_module_manager.ewp</path>
|
||||
</project>
|
||||
<project>
|
||||
<path>$WS_DIR$\tx.ewp</path>
|
||||
</project>
|
||||
<project>
|
||||
<path>$WS_DIR$\txm.ewp</path>
|
||||
</project>
|
||||
<batchBuild />
|
||||
</workspace>
|
||||
177
ports_module/cortex_r4/iar/example_build/cstartup.s
Normal file
177
ports_module/cortex_r4/iar/example_build/cstartup.s
Normal file
@@ -0,0 +1,177 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Part one of the system initialization code,
|
||||
;; contains low-level
|
||||
;; initialization.
|
||||
;;
|
||||
;; Copyright 2007-2017 IAR Systems AB.
|
||||
;;
|
||||
;; $Revision: 112610 $
|
||||
;;
|
||||
|
||||
MODULE ?cstartup
|
||||
|
||||
;; Forward declaration of sections.
|
||||
SECTION IRQ_STACK:DATA:NOROOT(3)
|
||||
SECTION FIQ_STACK:DATA:NOROOT(3)
|
||||
SECTION CSTACK:DATA:NOROOT(3)
|
||||
SECTION SVC_STACK:DATA:NOROOT(3)
|
||||
SECTION ABT_STACK:DATA:NOROOT(3)
|
||||
;
|
||||
; The module in this file are included in the libraries, and may be
|
||||
; replaced by any user-defined modules that define the PUBLIC symbol
|
||||
; __iar_program_start or a user defined start symbol.
|
||||
;
|
||||
; To override the cstartup defined in the library, simply add your
|
||||
; modified version to the workbench project.
|
||||
|
||||
SECTION .intvec:CODE:NOROOT(2)
|
||||
|
||||
PUBLIC __vector
|
||||
PUBLIC __iar_program_start
|
||||
EXTERN Undefined_Handler
|
||||
EXTERN SWI_Handler
|
||||
EXTERN Prefetch_Handler
|
||||
EXTERN Abort_Handler
|
||||
EXTERN IRQ_Handler
|
||||
EXTERN FIQ_Handler
|
||||
|
||||
DATA
|
||||
|
||||
__iar_init$$done: ; The vector table is not needed
|
||||
; until after copy initialization is done
|
||||
|
||||
__vector: ; Make this a DATA label, so that stack usage
|
||||
; analysis doesn't consider it an uncalled fun
|
||||
|
||||
ARM
|
||||
|
||||
; All default exception handlers (except reset) are
|
||||
; defined as weak symbol definitions.
|
||||
; If a handler is defined by the application it will take precedence.
|
||||
LDR PC,Reset_Addr ; Reset
|
||||
LDR PC,Undefined_Addr ; Undefined instructions
|
||||
LDR PC,SWI_Addr ; Software interrupt (SWI/SVC)
|
||||
LDR PC,Prefetch_Addr ; Prefetch abort
|
||||
LDR PC,Abort_Addr ; Data abort
|
||||
DCD 0 ; RESERVED
|
||||
LDR PC,IRQ_Addr ; IRQ
|
||||
LDR PC,FIQ_Addr ; FIQ
|
||||
|
||||
DATA
|
||||
|
||||
Reset_Addr: DCD __iar_program_start
|
||||
Undefined_Addr: DCD Undefined_Handler
|
||||
SWI_Addr: DCD SWI_Handler
|
||||
Prefetch_Addr: DCD Prefetch_Handler
|
||||
Abort_Addr: DCD Abort_Handler
|
||||
IRQ_Addr: DCD IRQ_Handler
|
||||
FIQ_Addr: DCD FIQ_Handler
|
||||
|
||||
|
||||
; --------------------------------------------------
|
||||
; ?cstartup -- low-level system initialization code.
|
||||
;
|
||||
; After a reset execution starts here, the mode is ARM, supervisor
|
||||
; with interrupts disabled.
|
||||
;
|
||||
|
||||
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
|
||||
EXTERN __cmain
|
||||
REQUIRE __vector
|
||||
EXTWEAK __iar_init_core
|
||||
EXTWEAK __iar_init_vfp
|
||||
|
||||
|
||||
ARM
|
||||
|
||||
__iar_program_start:
|
||||
?cstartup:
|
||||
|
||||
;
|
||||
; Add initialization needed before setup of stackpointers here.
|
||||
;
|
||||
|
||||
;
|
||||
; Initialize the stack pointers.
|
||||
; The pattern below can be used for any of the exception stacks:
|
||||
; FIQ, IRQ, SVC, ABT, UND, SYS.
|
||||
; The USR mode uses the same stack as SYS.
|
||||
; The stack segments must be defined in the linker command file,
|
||||
; and be declared above.
|
||||
;
|
||||
|
||||
|
||||
; --------------------
|
||||
; Mode, correspords to bits 0-5 in CPSR
|
||||
|
||||
#define MODE_MSK 0x1F ; Bit mask for mode bits in CPSR
|
||||
|
||||
#define USR_MODE 0x10 ; User mode
|
||||
#define FIQ_MODE 0x11 ; Fast Interrupt Request mode
|
||||
#define IRQ_MODE 0x12 ; Interrupt Request mode
|
||||
#define SVC_MODE 0x13 ; Supervisor mode
|
||||
#define ABT_MODE 0x17 ; Abort mode
|
||||
#define UND_MODE 0x1B ; Undefined Instruction mode
|
||||
#define SYS_MODE 0x1F ; System mode
|
||||
|
||||
|
||||
MRS r0, cpsr ; Original PSR value
|
||||
|
||||
;; Set up the interrupt stack pointer.
|
||||
|
||||
BIC r0, r0, #MODE_MSK ; Clear the mode bits
|
||||
ORR r0, r0, #IRQ_MODE ; Set IRQ mode bits
|
||||
MSR cpsr_c, r0 ; Change the mode
|
||||
LDR r1, =SFE(IRQ_STACK) ; End of IRQ_STACK
|
||||
BIC sp,r1,#0x7 ; Make sure SP is 8 aligned
|
||||
|
||||
;; Set up the fast interrupt stack pointer.
|
||||
|
||||
BIC r0, r0, #MODE_MSK ; Clear the mode bits
|
||||
ORR r0, r0, #FIQ_MODE ; Set FIR mode bits
|
||||
MSR cpsr_c, r0 ; Change the mode
|
||||
LDR r1, =SFE(FIQ_STACK) ; End of FIQ_STACK
|
||||
BIC sp,r1,#0x7 ; Make sure SP is 8 aligned
|
||||
|
||||
;; Set up the SVC stack pointer.
|
||||
|
||||
CPS #SVC_MODE
|
||||
LDR r1, =SFE(SVC_STACK) ; End of SVC_STACK
|
||||
BIC sp,r1,#0x7 ; Make sure SP is 8 aligned
|
||||
|
||||
;; Set up the abort stack pointer.
|
||||
|
||||
CPS #ABT_MODE
|
||||
LDR r1, =SFE(ABT_STACK) ; End of ABT_STACK
|
||||
BIC sp,r1,#0x7 ; Make sure SP is 8 aligned
|
||||
|
||||
;; Set up the normal stack pointer.
|
||||
|
||||
BIC r0 ,r0, #MODE_MSK ; Clear the mode bits
|
||||
ORR r0 ,r0, #SYS_MODE ; Set System mode bits
|
||||
MSR cpsr_c, r0 ; Change the mode
|
||||
LDR r1, =SFE(CSTACK) ; End of CSTACK
|
||||
BIC sp,r1,#0x7 ; Make sure SP is 8 aligned
|
||||
|
||||
;; Turn on core features assumed to be enabled.
|
||||
FUNCALL __iar_program_start, __iar_init_core
|
||||
BL __iar_init_core
|
||||
|
||||
;; Initialize VFP (if needed).
|
||||
FUNCALL __iar_program_start, __iar_init_vfp
|
||||
BL __iar_init_vfp
|
||||
|
||||
;;;
|
||||
;;; Add more initialization here
|
||||
;;;
|
||||
|
||||
;;; Continue to __cmain for C-level initialization.
|
||||
|
||||
FUNCALL __iar_program_start, __cmain
|
||||
B __cmain
|
||||
|
||||
END
|
||||
376
ports_module/cortex_r4/iar/example_build/sample_threadx.c
Normal file
376
ports_module/cortex_r4/iar/example_build/sample_threadx.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
|
||||
threads of different priorities, using a message queue, semaphore, mutex, event flags group,
|
||||
byte pool, and block pool. */
|
||||
|
||||
#include "tx_api.h"
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD thread_0;
|
||||
TX_THREAD thread_1;
|
||||
TX_THREAD thread_2;
|
||||
TX_THREAD thread_3;
|
||||
TX_THREAD thread_4;
|
||||
TX_THREAD thread_5;
|
||||
TX_THREAD thread_6;
|
||||
TX_THREAD thread_7;
|
||||
TX_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 byte pool memory. */
|
||||
|
||||
UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
|
||||
|
||||
|
||||
|
||||
/* Define the counters used in the demo application... */
|
||||
|
||||
ULONG thread_0_counter;
|
||||
ULONG thread_1_counter;
|
||||
ULONG thread_1_messages_sent;
|
||||
ULONG thread_2_counter;
|
||||
ULONG thread_2_messages_received;
|
||||
ULONG thread_3_counter;
|
||||
ULONG thread_4_counter;
|
||||
ULONG thread_5_counter;
|
||||
ULONG thread_6_counter;
|
||||
ULONG thread_7_counter;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input);
|
||||
void thread_1_entry(ULONG thread_input);
|
||||
void thread_2_entry(ULONG thread_input);
|
||||
void thread_3_and_4_entry(ULONG thread_input);
|
||||
void thread_5_entry(ULONG thread_input);
|
||||
void thread_6_and_7_entry(ULONG thread_input);
|
||||
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
/* Enter the ThreadX kernel. */
|
||||
tx_kernel_enter();
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
|
||||
CHAR *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", byte_pool_memory, 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;
|
||||
}
|
||||
}
|
||||
2974
ports_module/cortex_r4/iar/example_build/sample_threadx.ewd
Normal file
2974
ports_module/cortex_r4/iar/example_build/sample_threadx.ewd
Normal file
File diff suppressed because it is too large
Load Diff
2137
ports_module/cortex_r4/iar/example_build/sample_threadx.ewp
Normal file
2137
ports_module/cortex_r4/iar/example_build/sample_threadx.ewp
Normal file
File diff suppressed because it is too large
Load Diff
49
ports_module/cortex_r4/iar/example_build/sample_threadx.icf
Normal file
49
ports_module/cortex_r4/iar/example_build/sample_threadx.icf
Normal file
@@ -0,0 +1,49 @@
|
||||
/*###ICF### Section handled by ICF editor, don't touch! ****/
|
||||
/*-Editor annotation file-*/
|
||||
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
|
||||
/*-Specials-*/
|
||||
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
|
||||
/*-Memory Regions-*/
|
||||
define symbol __ICFEDIT_region_ROM_start__ = 0x00000040;
|
||||
define symbol __ICFEDIT_region_ROM_end__ = 0x0013FFFF;
|
||||
define symbol __ICFEDIT_region_RAM_start__ = 0x08000000;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x0802FFFF;
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x200;
|
||||
define symbol __ICFEDIT_size_svcstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_irqstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_fiqstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_undstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_abtstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x200;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
||||
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
|
||||
|
||||
define symbol __region_DRAM_start__ = 0x80000000;
|
||||
define symbol __region_DRAM_end__ = 0x807FFFFF;
|
||||
define region DRAM_region = mem:[from __region_DRAM_start__ to __region_DRAM_end__];
|
||||
|
||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
|
||||
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
|
||||
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
|
||||
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
|
||||
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
|
||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
|
||||
do not initialize { section .noinit };
|
||||
|
||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||
|
||||
place in ROM_region { readonly };
|
||||
place in RAM_region { readwrite,
|
||||
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
|
||||
block UND_STACK, block ABT_STACK, block HEAP};
|
||||
place in DRAM_region { section DRAM };
|
||||
|
||||
place in RAM_region { last section FREE_MEM};
|
||||
425
ports_module/cortex_r4/iar/example_build/sample_threadx_module.c
Normal file
425
ports_module/cortex_r4/iar/example_build/sample_threadx_module.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel running as a module. It includes
|
||||
examples of eight threads of different priorities, using a message queue, semaphore, mutex,
|
||||
event flags group, byte pool, and block pool. */
|
||||
|
||||
/* Specify that this is a module! */
|
||||
|
||||
#define TXM_MODULE
|
||||
|
||||
|
||||
/* Include the ThreadX module definitions. */
|
||||
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define constants. */
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define the pool space in the bss section of the module. ULONG is used to
|
||||
get the word alignment. */
|
||||
|
||||
ULONG demo_module_pool_space[DEMO_BYTE_POOL_SIZE / 4];
|
||||
|
||||
|
||||
/* 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;
|
||||
ULONG semaphore_0_puts;
|
||||
ULONG event_0_sets;
|
||||
ULONG queue_0_sends;
|
||||
|
||||
/* 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);
|
||||
|
||||
void semaphore_0_notify(TX_SEMAPHORE *semaphore_ptr)
|
||||
{
|
||||
|
||||
if (semaphore_ptr == semaphore_0)
|
||||
semaphore_0_puts++;
|
||||
}
|
||||
|
||||
|
||||
void event_0_notify(TX_EVENT_FLAGS_GROUP *event_flag_group_ptr)
|
||||
{
|
||||
|
||||
if (event_flag_group_ptr == event_flags_0)
|
||||
event_0_sets++;
|
||||
}
|
||||
|
||||
|
||||
void queue_0_notify(TX_QUEUE *queue_ptr)
|
||||
{
|
||||
|
||||
if (queue_ptr == queue_0)
|
||||
queue_0_sends++;
|
||||
}
|
||||
|
||||
|
||||
/* Define the module start function. */
|
||||
|
||||
void demo_module_start(ULONG id)
|
||||
{
|
||||
|
||||
CHAR *pointer;
|
||||
|
||||
/* Allocate all the objects. In MPU mode, modules cannot allocate control blocks within
|
||||
their own memory area so they cannot corrupt the resident portion of ThreadX by overwriting
|
||||
the control block(s). */
|
||||
txm_module_object_allocate((void*)&thread_0, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_1, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_2, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_3, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_4, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_5, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_6, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&thread_7, sizeof(TX_THREAD));
|
||||
txm_module_object_allocate((void*)&queue_0, sizeof(TX_QUEUE));
|
||||
txm_module_object_allocate((void*)&semaphore_0, sizeof(TX_SEMAPHORE));
|
||||
txm_module_object_allocate((void*)&mutex_0, sizeof(TX_MUTEX));
|
||||
txm_module_object_allocate((void*)&event_flags_0, sizeof(TX_EVENT_FLAGS_GROUP));
|
||||
txm_module_object_allocate((void*)&byte_pool_0, sizeof(TX_BYTE_POOL));
|
||||
txm_module_object_allocate((void*)&block_pool_0, sizeof(TX_BLOCK_POOL));
|
||||
|
||||
|
||||
/* Create a byte memory pool from which to allocate the thread stacks. */
|
||||
tx_byte_pool_create(byte_pool_0, "module byte pool 0", demo_module_pool_space, 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module 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, "module queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
|
||||
|
||||
tx_queue_send_notify(queue_0, queue_0_notify);
|
||||
|
||||
/* Create the semaphore used by threads 3 and 4. */
|
||||
tx_semaphore_create(semaphore_0, "module semaphore 0", 1);
|
||||
|
||||
tx_semaphore_put_notify(semaphore_0, semaphore_0_notify);
|
||||
|
||||
/* Create the event flags group used by threads 1 and 5. */
|
||||
tx_event_flags_create(event_flags_0, "module event flags 0");
|
||||
|
||||
tx_event_flags_set_notify(event_flags_0, event_0_notify);
|
||||
|
||||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
|
||||
tx_mutex_create(mutex_0, "module 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, "module 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2974
ports_module/cortex_r4/iar/example_build/sample_threadx_module.ewd
Normal file
2974
ports_module/cortex_r4/iar/example_build/sample_threadx_module.ewd
Normal file
File diff suppressed because it is too large
Load Diff
2135
ports_module/cortex_r4/iar/example_build/sample_threadx_module.ewp
Normal file
2135
ports_module/cortex_r4/iar/example_build/sample_threadx_module.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
/*###ICF### Section handled by ICF editor, don't touch! ****/
|
||||
/*-Editor annotation file-*/
|
||||
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
|
||||
/*-Specials-*/
|
||||
/*-Memory Regions-*/
|
||||
define symbol __ICFEDIT_region_ROM_start__ = 0x00100000;
|
||||
define symbol __ICFEDIT_region_ROM_end__ = 0x0013FFFF;
|
||||
define symbol __ICFEDIT_region_RAM_start__ = 0x08000000;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x0800FFFF;
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0;
|
||||
define symbol __ICFEDIT_size_svcstack__ = 0;
|
||||
define symbol __ICFEDIT_size_irqstack__ = 0;
|
||||
define symbol __ICFEDIT_size_fiqstack__ = 0;
|
||||
define symbol __ICFEDIT_size_undstack__ = 0;
|
||||
define symbol __ICFEDIT_size_abtstack__ = 0;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x100;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
||||
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
|
||||
|
||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
do not initialize { section .noinit };
|
||||
|
||||
define movable block ROPI with alignment = 4, fixed order
|
||||
{
|
||||
ro object txm_module_preamble.o,
|
||||
ro,
|
||||
ro data
|
||||
};
|
||||
|
||||
define movable block RWPI with alignment = 8, fixed order, static base
|
||||
{
|
||||
rw,
|
||||
block HEAP
|
||||
};
|
||||
|
||||
place in ROM_region { block ROPI };
|
||||
place in RAM_region { block RWPI };
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Small demonstration of the ThreadX module manager. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD module_manager;
|
||||
TXM_MODULE_INSTANCE my_module;
|
||||
|
||||
UCHAR manager_stack[1024];
|
||||
|
||||
/* Define the object pool area. */
|
||||
|
||||
UCHAR object_memory[8192];
|
||||
|
||||
|
||||
/* Define the count of memory faults. */
|
||||
|
||||
ULONG memory_faults;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void module_manager_entry(ULONG thread_input);
|
||||
|
||||
|
||||
/* Define fault handler. */
|
||||
|
||||
VOID module_fault_handler(TX_THREAD *thread, TXM_MODULE_INSTANCE *module)
|
||||
{
|
||||
|
||||
/* Just increment the fault counter. */
|
||||
memory_faults++;
|
||||
}
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
/* Enter the ThreadX kernel. */
|
||||
tx_kernel_enter();
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
tx_thread_create(&module_manager, "Module Manager Thread", module_manager_entry, 0,
|
||||
manager_stack, DEMO_STACK_SIZE,
|
||||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the test threads. */
|
||||
|
||||
void module_manager_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
/* Initialize the module manager. */
|
||||
txm_module_manager_initialize((VOID *) 0x08020000, 0x10000);
|
||||
|
||||
txm_module_manager_object_pool_create(object_memory, sizeof(object_memory));
|
||||
|
||||
/* Register a fault handler. */
|
||||
txm_module_manager_memory_fault_notify(module_fault_handler);
|
||||
|
||||
/* Load the module that is already there, in this example it is placed there by the multiple image download. */
|
||||
txm_module_manager_in_place_load(&my_module, "my module", (VOID *) 0x00100000);
|
||||
|
||||
/* Enable 128 byte read/write shared memory region at 0x08025000. */
|
||||
txm_module_manager_external_memory_enable(&my_module, (void *) 0x08025000, 128, TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE);
|
||||
|
||||
/* Start the module. */
|
||||
txm_module_manager_start(&my_module);
|
||||
|
||||
/* Sleep for a while.... */
|
||||
tx_thread_sleep(300);
|
||||
|
||||
/* Stop the module. */
|
||||
txm_module_manager_stop(&my_module);
|
||||
|
||||
/* Unload the module. */
|
||||
txm_module_manager_unload(&my_module);
|
||||
|
||||
/* Load the module that is already there. */
|
||||
txm_module_manager_in_place_load(&my_module, "my module", (VOID *) 0x00100000);
|
||||
|
||||
/* Start the module again. */
|
||||
txm_module_manager_start(&my_module);
|
||||
|
||||
/* Now just spin... */
|
||||
while(1)
|
||||
{
|
||||
|
||||
tx_thread_sleep(100);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
/*###ICF### Section handled by ICF editor, don't touch! ****/
|
||||
/*-Editor annotation file-*/
|
||||
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
|
||||
/*-Specials-*/
|
||||
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
|
||||
/*-Memory Regions-*/
|
||||
define symbol __ICFEDIT_region_ROM_start__ = 0x00000040;
|
||||
define symbol __ICFEDIT_region_ROM_end__ = 0x000FFFFF; //Module in 0x00100000-0x0013FFFF
|
||||
define symbol __ICFEDIT_region_RAM_start__ = 0x08000000;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x0801FFFF; //Module in 0x08020000-0x0802FFFF
|
||||
/*-Sizes-*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x200;
|
||||
define symbol __ICFEDIT_size_svcstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_irqstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_fiqstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_undstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_abtstack__ = 0x100;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x200;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
||||
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
|
||||
|
||||
define symbol __region_DRAM_start__ = 0x80000000;
|
||||
define symbol __region_DRAM_end__ = 0x807FFFFF;
|
||||
define region DRAM_region = mem:[from __region_DRAM_start__ to __region_DRAM_end__];
|
||||
|
||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
|
||||
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
|
||||
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
|
||||
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
|
||||
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
|
||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
|
||||
do not initialize { section .noinit };
|
||||
|
||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||
|
||||
place in ROM_region { readonly };
|
||||
place in RAM_region { readwrite,
|
||||
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
|
||||
block UND_STACK, block ABT_STACK, block HEAP};
|
||||
place in DRAM_region { section DRAM };
|
||||
|
||||
place in RAM_region { last section FREE_MEM};
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0"?>
|
||||
<settings>
|
||||
<Stack>
|
||||
<FillEnabled>0</FillEnabled>
|
||||
<OverflowWarningsEnabled>1</OverflowWarningsEnabled>
|
||||
<WarningThreshold>90</WarningThreshold>
|
||||
<SpWarningsEnabled>1</SpWarningsEnabled>
|
||||
<WarnLogOnly>1</WarnLogOnly>
|
||||
<UseTrigger>1</UseTrigger>
|
||||
<TriggerName>main</TriggerName>
|
||||
<LimitSize>0</LimitSize>
|
||||
<ByteLimit>50</ByteLimit>
|
||||
</Stack>
|
||||
<Trace1>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>1</ShowSource>
|
||||
</Trace1>
|
||||
<DebugChecksum>
|
||||
<Checksum>157308190</Checksum>
|
||||
</DebugChecksum>
|
||||
<Disassembly>
|
||||
<InstrCount>0</InstrCount>
|
||||
<MixedMode>1</MixedMode>
|
||||
</Disassembly>
|
||||
<CodeCoverage>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>0</ShowSource>
|
||||
<HideCovered>0</HideCovered>
|
||||
</CodeCoverage>
|
||||
<DriverProfiling>
|
||||
<Enabled>0</Enabled>
|
||||
<Mode>1</Mode>
|
||||
<Graph>0</Graph>
|
||||
<Symbiont>0</Symbiont>
|
||||
</DriverProfiling>
|
||||
<CallStackLog>
|
||||
<Enabled>0</Enabled>
|
||||
</CallStackLog>
|
||||
<CallStackStripe>
|
||||
<ShowTiming>1</ShowTiming>
|
||||
</CallStackStripe>
|
||||
<Exceptions>
|
||||
<StopOnUncaught>_ 0</StopOnUncaught>
|
||||
<StopOnThrow>_ 0</StopOnThrow>
|
||||
</Exceptions>
|
||||
<TermIOLog>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
</TermIOLog>
|
||||
<LogFile>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
<Category>_ 0</Category>
|
||||
</LogFile>
|
||||
<CallStack>
|
||||
<ShowArgs>0</ShowArgs>
|
||||
</CallStack>
|
||||
<InterruptLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
<SumSortOrder>0</SumSortOrder>
|
||||
</InterruptLog>
|
||||
<DataLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
</DataLog>
|
||||
<DisassembleMode>
|
||||
<mode>0</mode>
|
||||
</DisassembleMode>
|
||||
<Breakpoints2>
|
||||
<Count>0</Count>
|
||||
</Breakpoints2>
|
||||
<Interrupts>
|
||||
<Enabled>1</Enabled>
|
||||
<Irq0>_ 0 10000 0 10000 1 0 0 100 0 1 "IRQ 1 0x18 CPSR.I"</Irq0>
|
||||
<Count>1</Count>
|
||||
</Interrupts>
|
||||
<MemConfig>
|
||||
<Base>1</Base>
|
||||
<Manual>0</Manual>
|
||||
<Ddf>1</Ddf>
|
||||
<TypeViol>0</TypeViol>
|
||||
<Stop>1</Stop>
|
||||
</MemConfig>
|
||||
<Aliases>
|
||||
<Count>0</Count>
|
||||
<SuppressDialog>0</SuppressDialog>
|
||||
</Aliases>
|
||||
<Simulator>
|
||||
<Freq>10000000</Freq>
|
||||
<FreqHi>0</FreqHi>
|
||||
<MultiCoreRunAll>1</MultiCoreRunAll>
|
||||
</Simulator>
|
||||
</settings>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0"?>
|
||||
<settings>
|
||||
<DebugChecksum>
|
||||
<Checksum>1819642867</Checksum>
|
||||
</DebugChecksum>
|
||||
<Stack>
|
||||
<FillEnabled>0</FillEnabled>
|
||||
<OverflowWarningsEnabled>1</OverflowWarningsEnabled>
|
||||
<WarningThreshold>90</WarningThreshold>
|
||||
<SpWarningsEnabled>1</SpWarningsEnabled>
|
||||
<WarnLogOnly>1</WarnLogOnly>
|
||||
<UseTrigger>1</UseTrigger>
|
||||
<TriggerName>main</TriggerName>
|
||||
<LimitSize>0</LimitSize>
|
||||
<ByteLimit>50</ByteLimit>
|
||||
</Stack>
|
||||
<Disassembly>
|
||||
<InstrCount>0</InstrCount>
|
||||
<MixedMode>1</MixedMode>
|
||||
</Disassembly>
|
||||
<CodeCoverage>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>0</ShowSource>
|
||||
<HideCovered>0</HideCovered>
|
||||
</CodeCoverage>
|
||||
<Trace1>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>1</ShowSource>
|
||||
</Trace1>
|
||||
<Exceptions>
|
||||
<StopOnUncaught>_ 0</StopOnUncaught>
|
||||
<StopOnThrow>_ 0</StopOnThrow>
|
||||
</Exceptions>
|
||||
<CallStack>
|
||||
<ShowArgs>0</ShowArgs>
|
||||
</CallStack>
|
||||
<DriverProfiling>
|
||||
<Enabled>0</Enabled>
|
||||
<Mode>1</Mode>
|
||||
<Graph>0</Graph>
|
||||
<Symbiont>0</Symbiont>
|
||||
</DriverProfiling>
|
||||
<CallStackLog>
|
||||
<Enabled>0</Enabled>
|
||||
</CallStackLog>
|
||||
<CallStackStripe>
|
||||
<ShowTiming>1</ShowTiming>
|
||||
</CallStackStripe>
|
||||
<TermIOLog>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
</TermIOLog>
|
||||
<LogFile>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
<Category>_ 0</Category>
|
||||
</LogFile>
|
||||
<InterruptLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
<SumSortOrder>0</SumSortOrder>
|
||||
</InterruptLog>
|
||||
<DataLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
</DataLog>
|
||||
<DisassembleMode>
|
||||
<mode>0</mode>
|
||||
</DisassembleMode>
|
||||
<Breakpoints2>
|
||||
<Count>0</Count>
|
||||
</Breakpoints2>
|
||||
<Interrupts>
|
||||
<Enabled>1</Enabled>
|
||||
<Irq0>_ 0 10000 0 10000 1 0 0 100 0 1 "IRQ 1 0x18 CPSR.I"</Irq0>
|
||||
<Count>1</Count>
|
||||
</Interrupts>
|
||||
<MemConfig>
|
||||
<Base>1</Base>
|
||||
<Manual>0</Manual>
|
||||
<Ddf>1</Ddf>
|
||||
<TypeViol>0</TypeViol>
|
||||
<Stop>1</Stop>
|
||||
</MemConfig>
|
||||
<Aliases>
|
||||
<Count>0</Count>
|
||||
<SuppressDialog>0</SuppressDialog>
|
||||
</Aliases>
|
||||
<Simulator>
|
||||
<Freq>10000000</Freq>
|
||||
<FreqHi>0</FreqHi>
|
||||
<MultiCoreRunAll>1</MultiCoreRunAll>
|
||||
</Simulator>
|
||||
</settings>
|
||||
2974
ports_module/cortex_r4/iar/example_build/tx.ewd
Normal file
2974
ports_module/cortex_r4/iar/example_build/tx.ewd
Normal file
File diff suppressed because it is too large
Load Diff
2880
ports_module/cortex_r4/iar/example_build/tx.ewp
Normal file
2880
ports_module/cortex_r4/iar/example_build/tx.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,408 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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"
|
||||
;
|
||||
;
|
||||
SVC_MODE DEFINE 0x13 ; SVC mode
|
||||
ABT_MODE DEFINE 0x17 ; ABT mode
|
||||
SYS_MODE DEFINE 0x1F ; SYS mode
|
||||
THUMB_MASK DEFINE 0x20 ; Thumb bit (5) of CPSR/SPSR
|
||||
;
|
||||
|
||||
EXTERN _tx_thread_system_stack_ptr
|
||||
EXTERN _tx_initialize_unused_memory
|
||||
EXTERN _tx_thread_context_save
|
||||
; EXTERN _tx_thread_vectored_context_save
|
||||
EXTERN _tx_thread_context_restore
|
||||
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
EXTERN _tx_thread_irq_nesting_start
|
||||
EXTERN _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
|
||||
EXTERN _tx_timer_interrupt
|
||||
EXTERN ?cstartup
|
||||
EXTERN _tx_build_options
|
||||
EXTERN _tx_version_id
|
||||
;
|
||||
;
|
||||
;
|
||||
;/* Define the FREE_MEM segment that will specify where free memory is
|
||||
; defined. This must also be located in at the end of other RAM segments
|
||||
; in the linker control file. The value of this segment is what is passed
|
||||
; to tx_application_define. */
|
||||
;
|
||||
RSEG FREE_MEM:DATA
|
||||
PUBLIC __tx_free_memory_start
|
||||
__tx_free_memory_start
|
||||
DS32 4
|
||||
;
|
||||
;
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_initialize_low_level Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function is responsible for any low-level processor */
|
||||
;/* initialization, including setting up interrupt vectors, setting */
|
||||
;/* up a periodic timer interrupt source, saving the system stack */
|
||||
;/* pointer for use in ISR processing later, and finding the first */
|
||||
;/* available RAM memory address for tx_application_define. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_initialize_low_level(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
ARM
|
||||
PUBLIC _tx_initialize_low_level
|
||||
_tx_initialize_low_level
|
||||
;
|
||||
; /****** NOTE ****** The IAR 4.11a and above releases call main in SYS mode. */
|
||||
;
|
||||
; /* For modules, stay in SYS mode and disable interrupts. */
|
||||
CPSID i
|
||||
;
|
||||
; /* Pickup the start of free memory. */
|
||||
;
|
||||
LDR r0, =__tx_free_memory_start ; Get end of non-initialized RAM area
|
||||
;
|
||||
; /* Save the system stack pointer. */
|
||||
; _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
|
||||
;
|
||||
; /* Save the first available memory address. */
|
||||
; _tx_initialize_unused_memory = (VOID_PTR) FREE_MEM;
|
||||
;
|
||||
LDR r2, =_tx_initialize_unused_memory ; Pickup unused memory ptr address
|
||||
STR r0, [r2, #0] ; Save first free memory address
|
||||
;
|
||||
; /* Setup Timer for periodic interrupts. */
|
||||
;
|
||||
; /* Done, return to caller. */
|
||||
;
|
||||
BX lr ; Return to caller
|
||||
;}
|
||||
;
|
||||
;/* Define shells for each of the interrupt vectors. */
|
||||
;
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC __tx_undefined
|
||||
__tx_undefined
|
||||
B __tx_undefined ; Undefined handler
|
||||
;
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC __tx_reserved_handler
|
||||
__tx_reserved_handler
|
||||
B __tx_reserved_handler ; Reserved exception handler
|
||||
;
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC __tx_irq_handler
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC __tx_irq_processing_return
|
||||
PUBLIC IRQ_Handler
|
||||
__tx_irq_handler
|
||||
IRQ_Handler
|
||||
;
|
||||
; /* Jump to context save to save system context. */
|
||||
B _tx_thread_context_save
|
||||
__tx_irq_processing_return
|
||||
;
|
||||
; /* At this point execution is still in the IRQ mode. The CPSR, point of
|
||||
; interrupt, and all C scratch registers are available for use. In
|
||||
; addition, IRQ interrupts may be re-enabled - with certain restrictions -
|
||||
; if nested IRQ interrupts are desired. Interrupts may be re-enabled over
|
||||
; small code sequences where lr is saved before enabling interrupts and
|
||||
; restored after interrupts are again disabled. */
|
||||
;
|
||||
; /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
|
||||
; from IRQ mode with interrupts disabled. This routine switches to the
|
||||
; system mode and returns with IRQ interrupts enabled.
|
||||
;
|
||||
; NOTE: It is very important to ensure all IRQ interrupts are cleared
|
||||
; prior to enabling nested IRQ interrupts. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_start
|
||||
#endif
|
||||
;
|
||||
; /* For debug purpose, execute the timer interrupt processing here. In
|
||||
; a real system, some kind of status indication would have to be checked
|
||||
; before the timer interrupt handler could be called. */
|
||||
;
|
||||
BL _tx_timer_interrupt ; Timer interrupt handler
|
||||
;
|
||||
; /* Application IRQ handlers can be called here! */
|
||||
;
|
||||
; /* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
; service must be called before returning to _tx_thread_context_restore.
|
||||
; This routine returns in processing in IRQ mode with interrupts disabled. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
;
|
||||
; /* Jump to context restore to restore system context. */
|
||||
B _tx_thread_context_restore
|
||||
;
|
||||
;
|
||||
; /* This is an example of a vectored IRQ handler. */
|
||||
;
|
||||
; RSEG .text:CODE:NOROOT(2)
|
||||
; PUBLIC __tx_example_vectored_irq_handler
|
||||
;__tx_example_vectored_irq_handler
|
||||
;
|
||||
; /* Jump to context save to save system context. */
|
||||
; STMDB sp!, {r0-r3} ; Save some scratch registers
|
||||
; MRS r0, SPSR ; Pickup saved SPSR
|
||||
; SUB lr, lr, #4 ; Adjust point of interrupt
|
||||
; STMDB sp!, {r0, r10, r12, lr} ; Store other registers
|
||||
; BL _tx_thread_vectored_context_save
|
||||
;
|
||||
; /* At this point execution is still in the IRQ mode. The CPSR, point of
|
||||
; interrupt, and all C scratch registers are available for use. In
|
||||
; addition, IRQ interrupts may be re-enabled - with certain restrictions -
|
||||
; if nested IRQ interrupts are desired. Interrupts may be re-enabled over
|
||||
; small code sequences where lr is saved before enabling interrupts and
|
||||
; restored after interrupts are again disabled. */
|
||||
;
|
||||
; /* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
|
||||
; from IRQ mode with interrupts disabled. This routine switches to the
|
||||
; system mode and returns with IRQ interrupts enabled.
|
||||
;
|
||||
; NOTE: It is very important to ensure all IRQ interrupts are cleared
|
||||
; prior to enabling nested IRQ interrupts. */
|
||||
;#ifdef TX_ENABLE_IRQ_NESTING
|
||||
; BL _tx_thread_irq_nesting_start
|
||||
;#endif
|
||||
;
|
||||
; /* Application IRQ handler is called here! */
|
||||
;
|
||||
; /* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
; service must be called before returning to _tx_thread_context_restore.
|
||||
; This routine returns in processing in IRQ mode with interrupts disabled. */
|
||||
;#ifdef TX_ENABLE_IRQ_NESTING
|
||||
; BL _tx_thread_irq_nesting_end
|
||||
;#endif
|
||||
;
|
||||
; /* Jump to context restore to restore system context. */
|
||||
; B _tx_thread_context_restore
|
||||
;
|
||||
;
|
||||
; /* FIQ Handler */
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC __tx_fiq_handler
|
||||
__tx_fiq_handler
|
||||
B __tx_fiq_handler ; FIQ interrupt handler
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* __tx_prefetch_handler & __tx_abort_handler Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function handles MPU exceptions and fills the */
|
||||
;/* _txm_module_manager_memory_fault_info struct. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* _txm_module_manager_memory_fault_handler */
|
||||
;/* _tx_execution_thread_exit */
|
||||
;/* _tx_thread_schedule */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* MMU exceptions */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
|
||||
; *******************************************************************
|
||||
; MPU Exception Handling
|
||||
; *******************************************************************
|
||||
EXTERN _tx_thread_system_state
|
||||
EXTERN _txm_module_manager_memory_fault_info
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _txm_module_manager_memory_fault_handler
|
||||
EXTERN _tx_execution_thread_exit
|
||||
EXTERN _tx_thread_schedule
|
||||
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC Prefetch_Handler
|
||||
PUBLIC Abort_Handler
|
||||
PUBLIC __tx_prefetch_handler
|
||||
PUBLIC __tx_abort_handler
|
||||
__tx_prefetch_handler
|
||||
__tx_abort_handler
|
||||
Prefetch_Handler
|
||||
Abort_Handler
|
||||
STMDB sp!, {r0-r3} ; Save some working registers
|
||||
LDR r3, =_tx_thread_system_state ; Pickup address of system state var
|
||||
LDR r2, [r3, #0] ; Pickup system state
|
||||
ADD r2, r2, #1 ; Increment the interrupt counter
|
||||
STR r2, [r3, #0] ; Store it back in the variable
|
||||
;
|
||||
; /* Now pickup and store all the fault related information. */
|
||||
;
|
||||
; Pickup the memory fault info struct
|
||||
LDR r3, =_txm_module_manager_memory_fault_info
|
||||
LDR r0, =_tx_thread_current_ptr ; Build current thread pointer address
|
||||
LDR r1, [r0] ; Pickup the current thread pointer
|
||||
STR r1, [r3, #0] ; Save current thread pointer
|
||||
|
||||
MRC p15, 0, r0, c6, c0, 0 ; Read DFAR
|
||||
STR r0, [r3, #8] ; Save DFAR
|
||||
|
||||
CMP r0, #0 ; Was it a data or instruction fault?
|
||||
SUBEQ lr, lr, #4 ; Adjust point of exception for instruction
|
||||
SUBNE lr, lr, #8 ; Adjust point of exception for data
|
||||
STR lr, [r3, #4] ; Save point of fault
|
||||
|
||||
MRC p15, 0, r0, c5, c0, 0 ; Read DFSR
|
||||
STR r0, [r3, #12] ; Save DFSR
|
||||
MRC p15, 0, r0, c6, c0, 2 ; Read IFAR
|
||||
STR r0, [r3, #16] ; Save IFAR
|
||||
MRC p15, 0, r0, c5, c0, 1 ; Read IFSR
|
||||
STR r0, [r3, #20] ; Save IFSR
|
||||
MOV r0, #0 ; Build zero register
|
||||
MCR p15, 0, r0, c6, c0, 0 ; Clear DFAR
|
||||
MCR p15, 0, r0, c5, c0, 0 ; Clear DFSR
|
||||
MCR p15, 0, r0, c6, c0, 2 ; Clear IFAR
|
||||
MCR p15, 0, r0, c5, c0, 1 ; Clear IFSR
|
||||
|
||||
; Save registers r0-r12
|
||||
POP {r0-r2}
|
||||
STR r0, [r3, #28] ; Save r0
|
||||
STR r1, [r3, #32] ; Save r1
|
||||
STR r2, [r3, #36] ; Save r2
|
||||
POP {r0}
|
||||
STR r0, [r3, #40] ; Save r3
|
||||
STR r4, [r3, #44] ; Save r4
|
||||
STR r5, [r3, #48] ; Save r5
|
||||
STR r6, [r3, #52] ; Save r6
|
||||
STR r7, [r3, #56] ; Save r7
|
||||
STR r8, [r3, #60] ; Save r8
|
||||
STR r9, [r3, #64] ; Save r9
|
||||
STR r10,[r3, #68] ; Save r10
|
||||
STR r11,[r3, #72] ; Save r11
|
||||
STR r12,[r3, #76] ; Save r12
|
||||
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
MOV r0, lr ; Pickup lr
|
||||
MOV r1, sp ; Pickup sp
|
||||
CPS #ABT_MODE ; Back to ABT mode
|
||||
STR r0, [r3, #80] ; Save lr
|
||||
STR r1, [r3, #24] ; Save sp
|
||||
MRS r0, SPSR ; Pickup SPSR
|
||||
STR r0, [r3, #84] ; Save SPSR
|
||||
ORR r0, r0, #SYS_MODE ; Return into SYS mode
|
||||
BIC r0, r0, #THUMB_MASK ; Clear THUMB mode
|
||||
MSR SPSR_c, r0 ; Save SPSR
|
||||
|
||||
; Call memory manager fault handler
|
||||
BL _txm_module_manager_memory_fault_handler
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
;
|
||||
BL _tx_execution_thread_exit ; Call the thread exit function
|
||||
#endif
|
||||
|
||||
LDR r0, =_tx_thread_system_state ; Pickup address of system state
|
||||
LDR r1, [r0] ; Pickup system state
|
||||
SUB r1, r1, #1 ; Decrement
|
||||
STR r1, [r0] ; Store new system state
|
||||
|
||||
MOV r1, #0 ; Build NULL value
|
||||
LDR r0, =_tx_thread_current_ptr ; Pickup address of current thread pointer
|
||||
STR r1, [r0] ; Clear current thread pointer
|
||||
|
||||
; Return from exception
|
||||
LDR lr, =_tx_thread_schedule ; Load scheduler address
|
||||
MOVS pc, lr ; Return to scheduler
|
||||
; *******************************************************************
|
||||
; End of MMU exception handling.
|
||||
; *******************************************************************
|
||||
;
|
||||
BUILD_OPTIONS
|
||||
DC32 _tx_build_options ; Reference to ensure it comes in
|
||||
VERSION_ID
|
||||
DC32 _tx_version_id ; Reference to ensure it comes in
|
||||
END
|
||||
|
||||
2477
ports_module/cortex_r4/iar/example_build/txm.ewp
Normal file
2477
ports_module/cortex_r4/iar/example_build/txm.ewp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
SECTION .text:CODE
|
||||
|
||||
AAPCS INTERWORK, ROPI, RWPI_COMPATIBLE, VFP_COMPATIBLE
|
||||
PRESERVE8
|
||||
|
||||
/* Define public symbols. */
|
||||
|
||||
PUBLIC __txm_module_preamble
|
||||
|
||||
|
||||
/* Define application-specific start/stop entry points for the module. */
|
||||
|
||||
EXTERN demo_module_start
|
||||
|
||||
|
||||
/* Define common external refrences. */
|
||||
|
||||
EXTERN _txm_module_thread_shell_entry
|
||||
EXTERN _txm_module_callback_request_thread_entry
|
||||
EXTERN ROPI$$Length
|
||||
EXTERN RWPI$$Length
|
||||
|
||||
DATA
|
||||
__txm_module_preamble:
|
||||
DC32 0x4D4F4455 ; Module ID
|
||||
DC32 0x6 ; Module Major Version
|
||||
DC32 0x1 ; Module Minor Version
|
||||
DC32 32 ; Module Preamble Size in 32-bit words
|
||||
DC32 0x12345678 ; Module ID (application defined)
|
||||
DC32 0x00000001 ; Module Properties where:
|
||||
; Bits 31-24: Compiler ID
|
||||
; 0 -> IAR
|
||||
; 1 -> RVDS
|
||||
; 2 -> GNU
|
||||
; Bits 23-1: Reserved
|
||||
; Bit 0: 0 -> Privileged mode execution (no MPU protection)
|
||||
; 1 -> User mode execution (MPU protection)
|
||||
DC32 _txm_module_thread_shell_entry - . - 0 ; Module Shell Entry Point
|
||||
DC32 demo_module_start - . - 0 ; Module Start Thread Entry Point
|
||||
DC32 0 ; Module Stop Thread Entry Point
|
||||
DC32 1 ; Module Start/Stop Thread Priority
|
||||
DC32 1022 ; Module Start/Stop Thread Stack Size
|
||||
DC32 _txm_module_callback_request_thread_entry - . - 0 ; Module Callback Thread Entry
|
||||
DC32 1 ; Module Callback Thread Priority
|
||||
DC32 1022 ; Module Callback Thread Stack Size
|
||||
DC32 ROPI$$Length ; Module Code Size
|
||||
DC32 RWPI$$Length ; Module Data Size
|
||||
DC32 0 ; Reserved 0
|
||||
DC32 0 ; Reserved 1
|
||||
DC32 0 ; Reserved 2
|
||||
DC32 0 ; Reserved 3
|
||||
DC32 0 ; Reserved 4
|
||||
DC32 0 ; Reserved 5
|
||||
DC32 0 ; Reserved 6
|
||||
DC32 0 ; Reserved 7
|
||||
DC32 0 ; Reserved 8
|
||||
DC32 0 ; Reserved 9
|
||||
DC32 0 ; Reserved 10
|
||||
DC32 0 ; Reserved 11
|
||||
DC32 0 ; Reserved 12
|
||||
DC32 0 ; Reserved 13
|
||||
DC32 0 ; Reserved 14
|
||||
DC32 0 ; Reserved 15
|
||||
|
||||
END
|
||||
|
||||
|
||||
411
ports_module/cortex_r4/iar/inc/tx_port.h
Normal file
411
ports_module/cortex_r4/iar/inc/tx_port.h
Normal file
@@ -0,0 +1,411 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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-R4/IAR */
|
||||
/* 6.1.6 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
|
||||
/* macro definition, */
|
||||
/* resulting in version 6.1.6 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#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>
|
||||
#include <intrinsics.h>
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX ARM port. */
|
||||
|
||||
#define TX_INT_DISABLE 0x80 /* Disable IRQ interrupts */
|
||||
#define TX_INT_ENABLE 0x00 /* Enable IRQ interrupts */
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
|
||||
#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_IRQ_NESTING
|
||||
#define TX_IRQ_NESTING_ENABLED 1
|
||||
#else
|
||||
#define TX_IRQ_NESTING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (TX_IRQ_NESTING_ENABLED)
|
||||
|
||||
|
||||
/* Define the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_DISABLE_INLINE
|
||||
#else
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
#define TX_THREAD_EXTENSION_1
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; \
|
||||
VOID *tx_thread_module_instance_ptr; \
|
||||
VOID *tx_thread_module_entry_info_ptr; \
|
||||
ULONG tx_thread_module_current_user_mode; \
|
||||
ULONG tx_thread_module_user_mode; \
|
||||
VOID *tx_thread_module_kernel_stack_start; \
|
||||
VOID *tx_thread_module_kernel_stack_end; \
|
||||
ULONG tx_thread_module_kernel_stack_size; \
|
||||
VOID *tx_thread_module_stack_ptr; \
|
||||
VOID *tx_thread_module_stack_start; \
|
||||
VOID *tx_thread_module_stack_end; \
|
||||
ULONG tx_thread_module_stack_size; \
|
||||
VOID *tx_thread_module_reserved; \
|
||||
VOID *tx_thread_iar_tls_pointer;
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; \
|
||||
VOID *tx_thread_module_instance_ptr; \
|
||||
VOID *tx_thread_module_entry_info_ptr; \
|
||||
ULONG tx_thread_module_current_user_mode; \
|
||||
ULONG tx_thread_module_user_mode; \
|
||||
VOID *tx_thread_module_kernel_stack_start; \
|
||||
VOID *tx_thread_module_kernel_stack_end; \
|
||||
ULONG tx_thread_module_kernel_stack_size; \
|
||||
VOID *tx_thread_module_stack_ptr; \
|
||||
VOID *tx_thread_module_stack_start; \
|
||||
VOID *tx_thread_module_stack_end; \
|
||||
ULONG tx_thread_module_stack_size; \
|
||||
VOID *tx_thread_module_reserved;
|
||||
#endif
|
||||
#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 VOID *tx_event_flags_group_module_instance; \
|
||||
VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
|
||||
VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
|
||||
#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
|
||||
VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
|
||||
#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#if (__VER__ < 8000000)
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
|
||||
#else
|
||||
void *_tx_iar_create_per_thread_tls_area(void);
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
void __iar_Initlocks(void);
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
|
||||
#endif
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
#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
|
||||
|
||||
#if __CORE__ > __ARM4TM__
|
||||
|
||||
#if __CPU_MODE__ == 2
|
||||
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \
|
||||
b = (UINT) __CLZ(m); \
|
||||
b = 31 - b;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
||||
/* First, check and see what mode the file is being compiled in. The IAR compiler
|
||||
defines __CPU_MODE__ to 1, if the Thumb mode is present, and 2 if ARM 32-bit mode
|
||||
is present. If ARM 32-bit mode is present, the fast CPSR manipulation macros
|
||||
are available. Otherwise, if Thumb mode is present, we must use function calls. */
|
||||
|
||||
#ifdef TX_DISABLE_INLINE
|
||||
|
||||
UINT _tx_thread_interrupt_disable(void);
|
||||
void _tx_thread_interrupt_restore(UINT old_posture);
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||
|
||||
#else
|
||||
#if __CPU_MODE__ == 2
|
||||
|
||||
#if (__VER__ < 8002000)
|
||||
__intrinsic unsigned long __get_CPSR();
|
||||
__intrinsic void __set_CPSR( unsigned long );
|
||||
#endif
|
||||
|
||||
|
||||
#if (__VER__ < 8002000)
|
||||
#define TX_INTERRUPT_SAVE_AREA ULONG interrupt_save;
|
||||
#else
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
#endif
|
||||
|
||||
#define TX_DISABLE interrupt_save = __get_CPSR(); \
|
||||
__set_CPSR(interrupt_save | TX_INT_DISABLE);
|
||||
#define TX_RESTORE __set_CPSR(interrupt_save);
|
||||
|
||||
#else
|
||||
|
||||
UINT _tx_thread_interrupt_disable(void);
|
||||
void _tx_thread_interrupt_restore(UINT old_posture);
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||
|
||||
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||
|
||||
|
||||
/* Define VFP extension for the Cortex-R4. Each is assumed to be called in the context of the executing
|
||||
thread. */
|
||||
|
||||
void tx_thread_vfp_enable(void);
|
||||
void tx_thread_vfp_disable(void);
|
||||
|
||||
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-R4/IAR Version 6.1.6 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
347
ports_module/cortex_r4/iar/inc/txm_module_port.h
Normal file
347
ports_module/cortex_r4/iar/inc/txm_module_port.h
Normal file
@@ -0,0 +1,347 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* APPLICATION INTERFACE DEFINITION RELEASE */
|
||||
/* */
|
||||
/* txm_module_port.h Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file defines the basic module constants, interface structures, */
|
||||
/* and function prototypes. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE_PORT_H
|
||||
#define TXM_MODULE_PORT_H
|
||||
|
||||
/* Determine if the optional Modules user define file should be used. */
|
||||
|
||||
#ifdef TXM_MODULE_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
|
||||
/* Yes, include the user defines in txm_module_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "txm_module_user.h"
|
||||
#endif
|
||||
|
||||
/* It is assumed that the base ThreadX tx_port.h file has been modified to add the
|
||||
following extensions to the ThreadX thread control block (this code should replace
|
||||
the corresponding macro define in tx_port.h):
|
||||
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; \
|
||||
VOID *tx_thread_module_instance_ptr; \
|
||||
VOID *tx_thread_module_entry_info_ptr; \
|
||||
ULONG tx_thread_module_current_user_mode; \
|
||||
ULONG tx_thread_module_user_mode; \
|
||||
VOID *tx_thread_module_kernel_stack_start; \
|
||||
VOID *tx_thread_module_kernel_stack_end; \
|
||||
ULONG tx_thread_module_kernel_stack_size; \
|
||||
VOID *tx_thread_module_stack_ptr; \
|
||||
VOID *tx_thread_module_stack_start; \
|
||||
VOID *tx_thread_module_stack_end; \
|
||||
ULONG tx_thread_module_stack_size; \
|
||||
VOID *tx_thread_module_reserved; \
|
||||
VOID *tx_thread_iar_tls_pointer;
|
||||
|
||||
The following extensions must also be defined in tx_port.h:
|
||||
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \
|
||||
VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr);
|
||||
|
||||
#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \
|
||||
VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr);
|
||||
|
||||
#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \
|
||||
VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr);
|
||||
|
||||
#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* Define the kernel stack size for a module thread. */
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_SIZE
|
||||
#define TXM_MODULE_KERNEL_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
/* For the following 3 access control settings, change TEX and C, B, S (bits 5 through 0)
|
||||
* to reflect your system memory attributes (cache, shareable, memory type). */
|
||||
/* Code region access control: read-only, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_CODE_ACCESS_CONTROL 0x00000607
|
||||
/* Data region access control: execute never, read/write, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_DATA_ACCESS_CONTROL 0x00001307
|
||||
/* Shared region access control: execute never, read-only, outer & inner write-back, normal memory, shareable. */
|
||||
#define TXM_MODULE_MPU_SHARED_ACCESS_CONTROL 0x00001207
|
||||
|
||||
/* Define constants specific to the tools the module can be built with for this particular modules port. */
|
||||
|
||||
#define TXM_MODULE_IAR_COMPILER 0x00000000
|
||||
#define TXM_MODULE_RVDS_COMPILER 0x01000000
|
||||
#define TXM_MODULE_GNU_COMPILER 0x02000000
|
||||
#define TXM_MODULE_COMPILER_MASK 0xFF000000
|
||||
#define TXM_MODULE_OPTIONS_MASK 0x000000FF
|
||||
|
||||
|
||||
/* Define the properties for this particular module port. */
|
||||
|
||||
#define TXM_MODULE_MEMORY_PROTECTION_ENABLED
|
||||
|
||||
#ifdef TXM_MODULE_MEMORY_PROTECTION_ENABLED
|
||||
#define TXM_MODULE_REQUIRE_ALLOCATED_OBJECT_MEMORY
|
||||
#else
|
||||
#define TXM_MODULE_REQUIRE_LOCAL_OBJECT_MEMORY
|
||||
#endif
|
||||
|
||||
#define TXM_MODULE_USER_MODE 0x00000001
|
||||
#define TXM_MODULE_MEMORY_PROTECTION 0x00000001
|
||||
|
||||
|
||||
/* Define the supported options for this module. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_SUPPORTED_OPTIONS (TXM_MODULE_MEMORY_PROTECTION)
|
||||
#define TXM_MODULE_MANAGER_REQUIRED_OPTIONS 0
|
||||
|
||||
|
||||
/* Define offset adjustments according to the compiler used to build the module. */
|
||||
|
||||
#define TXM_MODULE_IAR_SHELL_ADJUST 24
|
||||
#define TXM_MODULE_IAR_START_ADJUST 28
|
||||
#define TXM_MODULE_IAR_STOP_ADJUST 32
|
||||
#define TXM_MODULE_IAR_CALLBACK_ADJUST 44
|
||||
|
||||
#define TXM_MODULE_RVDS_SHELL_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_START_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_STOP_ADJUST 0
|
||||
#define TXM_MODULE_RVDS_CALLBACK_ADJUST 0
|
||||
|
||||
#define TXM_MODULE_GNU_SHELL_ADJUST 24
|
||||
#define TXM_MODULE_GNU_START_ADJUST 28
|
||||
#define TXM_MODULE_GNU_STOP_ADJUST 32
|
||||
#define TXM_MODULE_GNU_CALLBACK_ADJUST 44
|
||||
|
||||
|
||||
/* Define other module port-specific constants. */
|
||||
|
||||
|
||||
/* Define INLINE_DECLARE to inline for IAR compiler. */
|
||||
|
||||
#define INLINE_DECLARE inline
|
||||
|
||||
/* Define the number of MPU entries assigned to the code and data sections.
|
||||
On Cortex-R parts, there are 12 total entries. ThreadX uses one for access
|
||||
to the kernel entry function, thus 11 remain for code and data protection. */
|
||||
#define TXM_MODULE_MPU_TOTAL_ENTRIES 12
|
||||
#define TXM_MODULE_MPU_CODE_ENTRIES 4
|
||||
#define TXM_MODULE_MPU_DATA_ENTRIES 4
|
||||
#define TXM_MODULE_MPU_SHARED_ENTRIES 3
|
||||
|
||||
#define TXM_MODULE_MPU_KERNEL_ENTRY_INDEX 0
|
||||
#define TXM_MODULE_MPU_SHARED_INDEX 9
|
||||
|
||||
/* There are 3 registers to set up each MPU region: DRACR, DRBAR, DRSR. */
|
||||
#define TXM_MODULE_MPU_REGISTER_COUNT 3
|
||||
|
||||
#define TXM_ENABLE_REGION 0x01
|
||||
|
||||
/* Shared memory region attributes. */
|
||||
#define TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE 1
|
||||
#define TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT 0x00000100
|
||||
|
||||
typedef struct TXM_MODULE_MPU_INFO_STRUCT
|
||||
{
|
||||
ULONG txm_module_mpu_region_address;
|
||||
ULONG txm_module_mpu_region_size;
|
||||
ULONG txm_module_mpu_region_attributes;
|
||||
} TXM_MODULE_MPU_INFO;
|
||||
/* Define the port-extensions to the module manager instance structure. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_PORT_EXTENSION \
|
||||
TXM_MODULE_MPU_INFO txm_module_instance_mpu_registers[TXM_MODULE_MPU_TOTAL_ENTRIES]; \
|
||||
ULONG txm_module_instance_shared_memory_count; \
|
||||
ULONG txm_module_instance_shared_memory_address[TXM_MODULE_MPU_SHARED_ENTRIES]; \
|
||||
ULONG txm_module_instance_shared_memory_length[TXM_MODULE_MPU_SHARED_ENTRIES];
|
||||
|
||||
|
||||
/* Define the memory fault information structure that is populated when a memory fault occurs. */
|
||||
|
||||
|
||||
typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT
|
||||
{
|
||||
TX_THREAD *txm_module_manager_memory_fault_info_thread_ptr;
|
||||
VOID *txm_module_manager_memory_fault_info_code_location;
|
||||
ULONG txm_module_manager_memory_fault_info_dfar;
|
||||
ULONG txm_module_manager_memory_fault_info_dfsr;
|
||||
ULONG txm_module_manager_memory_fault_info_ifar;
|
||||
ULONG txm_module_manager_memory_fault_info_ifsr;
|
||||
ULONG txm_module_manager_memory_fault_info_sp;
|
||||
ULONG txm_module_manager_memory_fault_info_r0;
|
||||
ULONG txm_module_manager_memory_fault_info_r1;
|
||||
ULONG txm_module_manager_memory_fault_info_r2;
|
||||
ULONG txm_module_manager_memory_fault_info_r3;
|
||||
ULONG txm_module_manager_memory_fault_info_r4;
|
||||
ULONG txm_module_manager_memory_fault_info_r5;
|
||||
ULONG txm_module_manager_memory_fault_info_r6;
|
||||
ULONG txm_module_manager_memory_fault_info_r7;
|
||||
ULONG txm_module_manager_memory_fault_info_r8;
|
||||
ULONG txm_module_manager_memory_fault_info_r9;
|
||||
ULONG txm_module_manager_memory_fault_info_r10;
|
||||
ULONG txm_module_manager_memory_fault_info_r11;
|
||||
ULONG txm_module_manager_memory_fault_info_r12;
|
||||
ULONG txm_module_manager_memory_fault_info_lr;
|
||||
ULONG txm_module_manager_memory_fault_info_cpsr;
|
||||
} TXM_MODULE_MANAGER_MEMORY_FAULT_INFO;
|
||||
|
||||
|
||||
#define TXM_MODULE_MANAGER_FAULT_INFO \
|
||||
TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info;
|
||||
|
||||
/* Define the macro to check the stack available in dispatch. */
|
||||
#define TXM_MODULE_MANAGER_CHECK_STACK_AVAILABLE
|
||||
|
||||
|
||||
/* Define the macro to check the code alignment. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) \
|
||||
{ \
|
||||
ULONG temp; \
|
||||
temp = (ULONG) module_location; \
|
||||
temp = temp & (code_alignment - 1); \
|
||||
if (temp) \
|
||||
{ \
|
||||
_tx_mutex_put(&_txm_module_manager_mutex); \
|
||||
return(TXM_MODULE_ALIGNMENT_ERROR); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to adjust the alignment and size for code/data areas. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size, data_alignment) _txm_module_manager_alignment_adjust(module_preamble, &code_size, &code_alignment, &data_size, &data_alignment);
|
||||
|
||||
|
||||
/* Define the macro to adjust the symbols in the module preamble. */
|
||||
|
||||
#define TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(properties, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust) \
|
||||
if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_IAR_COMPILER) \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_IAR_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_IAR_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_IAR_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_IAR_CALLBACK_ADJUST; \
|
||||
} \
|
||||
else if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_RVDS_COMPILER) \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_RVDS_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_RVDS_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_RVDS_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_RVDS_CALLBACK_ADJUST; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
shell_function_adjust = TXM_MODULE_GNU_SHELL_ADJUST; \
|
||||
start_function_adjust = TXM_MODULE_GNU_START_ADJUST; \
|
||||
stop_function_adjust = TXM_MODULE_GNU_STOP_ADJUST; \
|
||||
callback_function_adjust = TXM_MODULE_GNU_CALLBACK_ADJUST; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to populate the thread control block with module port-specific information.
|
||||
Check if the module is in user mode and set up txm_module_thread_entry_info_kernel_call_dispatcher accordingly.
|
||||
*/
|
||||
|
||||
#define TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance) \
|
||||
thread_ptr -> tx_thread_module_current_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION; \
|
||||
thread_ptr -> tx_thread_module_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION; \
|
||||
if (thread_ptr -> tx_thread_module_user_mode) \
|
||||
{ \
|
||||
thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_user_mode_entry; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_kernel_dispatch; \
|
||||
}
|
||||
|
||||
|
||||
/* Define the macro to populate the module control block with module port-specific information.
|
||||
If memory protection is enabled, set up the MPU registers.
|
||||
*/
|
||||
#define TXM_MODULE_MANAGER_MODULE_SETUP(module_instance) \
|
||||
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) \
|
||||
{ \
|
||||
_txm_module_manager_mm_register_setup(module_instance); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* Do nothing. */ \
|
||||
}
|
||||
|
||||
/* Define the macro to perform port-specific functions when unloading the module. */
|
||||
/* Nothing needs to be done for this port. */
|
||||
#define TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance)
|
||||
|
||||
|
||||
/* Define the macros to perform port-specific checks when passing pointers to the kernel. */
|
||||
|
||||
/* Define macro to make sure object is inside the module's data. */
|
||||
#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \
|
||||
_txm_module_manager_inside_data_check(module_instance, obj_ptr, obj_size)
|
||||
|
||||
/* Define some internal prototypes to this module port. */
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define txm_module_manager_memory_fault_notify _txm_module_manager_memory_fault_notify
|
||||
#endif
|
||||
|
||||
|
||||
#define TXM_MODULE_MANAGER_ADDITIONAL_PROTOTYPES \
|
||||
VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment); \
|
||||
ULONG _txm_module_manager_data_pointer_check(TXM_MODULE_INSTANCE *module_instance, ULONG pointer); \
|
||||
VOID _txm_module_manager_memory_fault_handler(VOID); \
|
||||
UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)); \
|
||||
VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \
|
||||
ULONG _txm_power_of_two_block_size(ULONG size); \
|
||||
ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length); \
|
||||
ULONG _txm_module_manager_region_size_get(ULONG block_size); \
|
||||
UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ULONG obj_ptr, UINT obj_size);
|
||||
|
||||
#define TXM_MODULE_MANAGER_VERSION_ID \
|
||||
CHAR _txm_module_manager_version_id[] = \
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Module Cortex-R4/MPU/IAR Version 6.1 *";
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TXM_MODULE
|
||||
#define TXM_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define TX_SOURCE_CODE
|
||||
#endif
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "txm_module.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/* Define the global module entry pointer from the start thread of the module. */
|
||||
|
||||
TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info;
|
||||
|
||||
|
||||
/* Define the dispatch function pointer used in the module implementation. */
|
||||
|
||||
ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3);
|
||||
|
||||
|
||||
/* Define the IAR startup code that clears the uninitialized global data and sets up the
|
||||
preset global variables. */
|
||||
|
||||
extern VOID __iar_data_init3(VOID);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_thread_shell_entry Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calls the specified entry function of the thread. It */
|
||||
/* also provides a place for the thread's entry function to return. */
|
||||
/* If the thread returns, this function places the thread in a */
|
||||
/* "COMPLETED" state. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to current thread */
|
||||
/* thread_info Pointer to thread entry info */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* __iar_data_init3 IAR global initialization function*/
|
||||
/* thread_entry Thread's entry function */
|
||||
/* tx_thread_resume Resume the module callback thread */
|
||||
/* _txm_module_thread_system_suspend Module thread suspension routine */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info)
|
||||
{
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
VOID (*entry_exit_notify)(TX_THREAD *, UINT);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if this is the start thread. If so, we must prepare the module for
|
||||
execution. If not, simply skip the C startup code. */
|
||||
if (thread_info -> txm_module_thread_entry_info_start_thread)
|
||||
{
|
||||
/* Initialize the IAR C environment. */
|
||||
__iar_data_init3();
|
||||
|
||||
/* Save the entry info pointer, for later use. */
|
||||
_txm_module_entry_info = thread_info;
|
||||
|
||||
/* Save the kernel function dispatch address. This is used to make all resident calls from
|
||||
the module. */
|
||||
_txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher;
|
||||
|
||||
/* Ensure that we have a valid pointer. */
|
||||
while (!_txm_module_kernel_call_dispatcher)
|
||||
{
|
||||
/* Loop here, if an error is present getting the dispatch function pointer!
|
||||
An error here typically indicates the resident portion of _tx_thread_schedule
|
||||
is not supporting the trap to obtain the function pointer. */
|
||||
}
|
||||
|
||||
/* Resume the module's callback thread, already created in the manager. */
|
||||
_txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread);
|
||||
}
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has been entered! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call current thread's entry function. */
|
||||
(thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter);
|
||||
|
||||
/* Suspend thread with a "completed" state. */
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_NOTIFY_CALLBACKS
|
||||
|
||||
/* Pickup the entry/exit application callback routine again. */
|
||||
entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify;
|
||||
|
||||
/* Determine if an application callback routine is specified. */
|
||||
if (entry_exit_notify != TX_NULL)
|
||||
{
|
||||
|
||||
/* Yes, notify application that this thread has exited! */
|
||||
(entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call actual thread suspension routine. */
|
||||
_txm_module_thread_system_suspend(thread_ptr);
|
||||
|
||||
#ifdef TX_SAFETY_CRITICAL
|
||||
|
||||
/* If we ever get here, raise safety critical exception. */
|
||||
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
804
ports_module/cortex_r4/iar/module_manager/src/tx_iar.c
Normal file
804
ports_module/cortex_r4/iar/module_manager/src/tx_iar.c
Normal file
@@ -0,0 +1,804 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** IAR Multithreaded Library Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Define IAR library for tools prior to version 8. */
|
||||
|
||||
#if (__VER__ < 8000000)
|
||||
|
||||
|
||||
/* IAR version 7 and below. */
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
|
||||
/* This implementation requires that the following macros are defined in the
|
||||
tx_port.h file and <yvals.h> is included with the following code segments:
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
|
||||
This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
|
||||
application.
|
||||
|
||||
Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
|
||||
*/
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
|
||||
#include <yvals.h>
|
||||
|
||||
|
||||
#if _MULTI_THREAD
|
||||
|
||||
TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
|
||||
UINT __tx_iar_system_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_system_lock_no_mutexes;
|
||||
UINT __tx_iar_system_lock_internal_errors;
|
||||
UINT __tx_iar_system_lock_isr_caller;
|
||||
|
||||
|
||||
/* Define the TLS access function for the IAR library. */
|
||||
|
||||
void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
|
||||
{
|
||||
|
||||
char _DLIB_TLS_MEMORY *p = 0;
|
||||
|
||||
/* Is there a current thread? */
|
||||
if (_tx_thread_current_ptr)
|
||||
p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
|
||||
else
|
||||
p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
|
||||
p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
|
||||
return (void _DLIB_TLS_MEMORY *) p;
|
||||
}
|
||||
|
||||
|
||||
/* Define mutexes for IAR library. */
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_LOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_system_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_system_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if _DLIB_FILE_DESCRIPTOR
|
||||
|
||||
TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
|
||||
UINT __tx_iar_file_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_file_lock_no_mutexes;
|
||||
UINT __tx_iar_file_lock_internal_errors;
|
||||
UINT __tx_iar_file_lock_isr_caller;
|
||||
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_FLOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_file_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_file_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
#endif /* _DLIB_FILE_DESCRIPTOR */
|
||||
|
||||
#endif /* _MULTI_THREAD */
|
||||
|
||||
#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
|
||||
|
||||
#else /* IAR version 8 and above. */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_initialize.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_mutex.h"
|
||||
|
||||
/* This implementation requires that the following macros are defined in the
|
||||
tx_port.h file and <yvals.h> is included with the following code segments:
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#include <yvals.h>
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
|
||||
#else
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
void *_tx_iar_create_per_thread_tls_area(void);
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
void __iar_Initlocks(void);
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
|
||||
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
|
||||
#else
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#endif
|
||||
|
||||
This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
|
||||
application.
|
||||
|
||||
Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
|
||||
*/
|
||||
|
||||
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
|
||||
|
||||
#include <DLib_threads.h>
|
||||
|
||||
|
||||
void * __aeabi_read_tp();
|
||||
|
||||
void* _tx_iar_create_per_thread_tls_area();
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
|
||||
|
||||
#pragma section="__iar_tls$$DATA"
|
||||
|
||||
/* Define the TLS access function for the IAR library. */
|
||||
void * __aeabi_read_tp(void)
|
||||
{
|
||||
void *p = 0;
|
||||
TX_THREAD *thread_ptr = _tx_thread_current_ptr;
|
||||
if (thread_ptr)
|
||||
{
|
||||
p = thread_ptr->tx_thread_iar_tls_pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = __section_begin("__iar_tls$$DATA");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Define the TLS creation and destruction to use malloc/free. */
|
||||
|
||||
void* _tx_iar_create_per_thread_tls_area()
|
||||
{
|
||||
UINT tls_size = __iar_tls_size();
|
||||
|
||||
/* Get memory for TLS. */
|
||||
void *p = malloc(tls_size);
|
||||
|
||||
/* Initialize TLS-area and run constructors for objects in TLS */
|
||||
__iar_tls_init(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
|
||||
{
|
||||
/* Destroy objects living in TLS */
|
||||
__call_thread_dtors();
|
||||
free(tls_ptr);
|
||||
}
|
||||
|
||||
#ifndef _MAX_LOCK
|
||||
#define _MAX_LOCK 4
|
||||
#endif
|
||||
|
||||
static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK];
|
||||
static UINT __tx_iar_system_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_system_lock_no_mutexes;
|
||||
UINT __tx_iar_system_lock_internal_errors;
|
||||
UINT __tx_iar_system_lock_isr_caller;
|
||||
|
||||
|
||||
/* Define mutexes for IAR library. */
|
||||
|
||||
void __iar_system_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_LOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_system_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_system_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_system_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
if (*m)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_system_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
if (*m)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_system_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_system_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if _DLIB_FILE_DESCRIPTOR
|
||||
|
||||
#include <stdio.h> /* Added to get access to FOPEN_MAX */
|
||||
#ifndef _MAX_FLOCK
|
||||
#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */
|
||||
#endif
|
||||
|
||||
|
||||
TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK];
|
||||
UINT __tx_iar_file_lock_next_free_mutex = 0;
|
||||
|
||||
|
||||
/* Define error counters, just for debug purposes. */
|
||||
|
||||
UINT __tx_iar_file_lock_no_mutexes;
|
||||
UINT __tx_iar_file_lock_internal_errors;
|
||||
UINT __tx_iar_file_lock_isr_caller;
|
||||
|
||||
|
||||
void __iar_file_Mtxinit(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT i;
|
||||
UINT status;
|
||||
TX_MUTEX *mutex_ptr;
|
||||
|
||||
|
||||
/* First, find a free mutex in the list. */
|
||||
for (i = 0; i < _MAX_FLOCK; i++)
|
||||
{
|
||||
|
||||
/* Setup a pointer to the start of the next free mutex. */
|
||||
mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
|
||||
|
||||
/* Check for wrap-around on the next free mutex. */
|
||||
if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Yes, set the free index back to 0. */
|
||||
__tx_iar_file_lock_next_free_mutex = 0;
|
||||
}
|
||||
|
||||
/* Is this mutex free? */
|
||||
if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
|
||||
{
|
||||
|
||||
/* Yes, this mutex is free, get out of the loop! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if a free mutex was found. */
|
||||
if (i >= _MAX_LOCK)
|
||||
{
|
||||
|
||||
/* Error! No more free mutexes! */
|
||||
|
||||
/* Increment the no mutexes error counter. */
|
||||
__tx_iar_file_lock_no_mutexes++;
|
||||
|
||||
/* Set return pointer to NULL. */
|
||||
*m = TX_NULL;
|
||||
|
||||
/* Return. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now create the ThreadX mutex for the IAR library. */
|
||||
status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
|
||||
|
||||
/* Determine if the creation was successful. */
|
||||
if (status == TX_SUCCESS)
|
||||
{
|
||||
|
||||
/* Yes, successful creation, return mutex pointer. */
|
||||
*m = (VOID *) mutex_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the internal error counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
|
||||
/* Return a NULL pointer to indicate an error. */
|
||||
*m = TX_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxdst(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
/* Simply delete the mutex. */
|
||||
_tx_mutex_delete((TX_MUTEX *) *m);
|
||||
}
|
||||
|
||||
void __iar_file_Mtxlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex locks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Get the mutex. */
|
||||
status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
|
||||
void __iar_file_Mtxunlock(__iar_Rmtx *m)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* Determine the caller's context. Mutex unlocks are only available from initialization and
|
||||
threads. */
|
||||
if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
|
||||
{
|
||||
|
||||
/* Release the mutex. */
|
||||
status = _tx_mutex_put((TX_MUTEX *) *m);
|
||||
|
||||
/* Check the status of the mutex release. */
|
||||
if (status)
|
||||
{
|
||||
|
||||
/* Internal error, increment the counter. */
|
||||
__tx_iar_file_lock_internal_errors++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Increment the ISR caller error. */
|
||||
__tx_iar_file_lock_isr_caller++;
|
||||
}
|
||||
}
|
||||
#endif /* _DLIB_FILE_DESCRIPTOR */
|
||||
|
||||
#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */
|
||||
|
||||
#endif /* IAR version 8 and above. */
|
||||
@@ -0,0 +1,239 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
;/* */
|
||||
;/* This software is licensed under the Microsoft Software License */
|
||||
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
;/* and in the root directory of this software. */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;/** */
|
||||
;/** ThreadX Component */
|
||||
;/** */
|
||||
;/** Thread */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
|
||||
IRQ_MODE EQU 0x12 ; IRQ mode
|
||||
SVC_MODE EQU 0x13 ; SVC mode
|
||||
SYS_MODE EQU 0x1F ; SYS mode
|
||||
DISABLE_INTS DEFINE 0x80 ; Disable IRQ interrupts
|
||||
THUMB_MASK DEFINE 0x20 ; Thumb bit mask
|
||||
|
||||
;
|
||||
EXTERN _tx_thread_system_state
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_thread_execute_ptr
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_thread_schedule
|
||||
EXTERN _tx_thread_preempt_disable
|
||||
EXTERN _tx_execution_isr_exit
|
||||
;
|
||||
;
|
||||
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_context_restore Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function restores the interrupt context if it is processing a */
|
||||
;/* nested interrupt. If not, it returns to the interrupt thread if no */
|
||||
;/* preemption is necessary. Otherwise, if preemption is necessary or */
|
||||
;/* if no thread was running, the function returns to the scheduler. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* _tx_thread_schedule Thread scheduling routine */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* ISRs Interrupt Service Routines */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_context_restore(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_context_restore
|
||||
ARM
|
||||
_tx_thread_context_restore
|
||||
;
|
||||
; /* Lockout interrupts. */
|
||||
;
|
||||
CPSID i ; Disable IRQ 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 r3, =_tx_thread_system_state ; Pickup address of system state var
|
||||
LDR r2, [r3] ; Pickup system state
|
||||
SUB r2, r2, #1 ; Decrement the counter
|
||||
STR r2, [r3] ; Store the counter
|
||||
CMP r2, #0 ; Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore ; If so, not a nested restore
|
||||
;
|
||||
; /* Interrupts are nested. */
|
||||
;
|
||||
; /* Just recover the saved registers and return to the point of
|
||||
; interrupt. */
|
||||
;
|
||||
LDMIA sp!, {r0, r10, r12, lr} ; Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 ; Put SPSR back
|
||||
LDMIA sp!, {r0-r3} ; Recover r0-r3
|
||||
MOVS pc, lr ; Return to point of interrupt
|
||||
;
|
||||
; }
|
||||
__tx_thread_not_nested_restore
|
||||
;
|
||||
; /* Determine if a thread was interrupted and no preemption is required. */
|
||||
; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||
; || (_tx_thread_preempt_disable))
|
||||
; {
|
||||
;
|
||||
LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread ptr
|
||||
LDR r0, [r1] ; Pickup actual current thread pointer
|
||||
CMP r0, #0 ; Is it NULL?
|
||||
BEQ __tx_thread_idle_system_restore ; Yes, idle system was interrupted
|
||||
;
|
||||
LDR r3, =_tx_thread_preempt_disable ; Pickup preempt disable address
|
||||
LDR r2, [r3] ; Pickup actual preempt disable flag
|
||||
CMP r2, #0 ; Is it set?
|
||||
BNE __tx_thread_no_preempt_restore ; Yes, don't preempt this thread
|
||||
LDR r3, =_tx_thread_execute_ptr ; Pickup address of execute thread ptr
|
||||
LDR r2, [r3] ; Pickup actual execute thread pointer
|
||||
CMP r0, r2 ; Is the same thread highest priority?
|
||||
BNE __tx_thread_preempt_restore ; No, preemption needs to happen
|
||||
;
|
||||
;
|
||||
__tx_thread_no_preempt_restore
|
||||
;
|
||||
; /* Restore interrupted thread or ISR. */
|
||||
;
|
||||
; /* Pickup the saved stack pointer. */
|
||||
; tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr;
|
||||
;
|
||||
; /* Recover the saved context and return to the point of interrupt. */
|
||||
;
|
||||
LDMIA sp!, {r0, r10, r12, lr} ; Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 ; Put SPSR back
|
||||
LDMIA sp!, {r0-r3} ; Recover r0-r3
|
||||
MOVS pc, lr ; Return to point of interrupt
|
||||
;
|
||||
; }
|
||||
; else
|
||||
; {
|
||||
__tx_thread_preempt_restore
|
||||
;
|
||||
LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers
|
||||
MOV r1, lr ; Save lr (point of interrupt)
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
STR r1, [sp, #-4]! ; Save point of interrupt on thread's stack
|
||||
STMDB sp!, {r4-r12, lr} ; Save upper half of registers on thread's stack
|
||||
MOV r4, r3 ; Save SPSR in r4
|
||||
CPS #IRQ_MODE ; Enter IRQ mode
|
||||
LDMIA sp!, {r0-r3} ; Recover r0-r3
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
STMDB sp!, {r0-r3} ; Save r0-r3 on thread's stack
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] ; Pickup current thread pointer
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
LDR r2, [r0, #144] ; Pickup the VFP enabled flag
|
||||
CMP r2, #0 ; Is the VFP enabled?
|
||||
BEQ _tx_skip_irq_vfp_save ; No, skip VFP IRQ save
|
||||
VMRS r2, FPSCR ; Pickup the FPSCR
|
||||
STR r2, [sp, #-4]! ; Save FPSCR
|
||||
VSTMDB sp!, {D0-D15} ; Save D0-D15
|
||||
_tx_skip_irq_vfp_save
|
||||
#endif
|
||||
|
||||
MOV r3, #1 ; Build interrupt stack type
|
||||
STMDB sp!, {r3, r4} ; Save interrupt stack type and SPSR
|
||||
STR sp, [r0, #8] ; Save stack pointer in thread control
|
||||
; block
|
||||
;
|
||||
; /* Save the remaining time-slice and disable it. */
|
||||
; if (_tx_timer_time_slice)
|
||||
; {
|
||||
;
|
||||
LDR r3, =_tx_timer_time_slice ; Pickup time-slice variable address
|
||||
LDR r2, [r3] ; Pickup time-slice
|
||||
CMP r2, #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 r2, [r0, #24] ; Save thread's time-slice
|
||||
MOV r2, #0 ; Clear value
|
||||
STR r2, [r3] ; Disable global time-slice flag
|
||||
;
|
||||
; }
|
||||
__tx_thread_dont_save_ts
|
||||
;
|
||||
;
|
||||
; /* Clear the current task pointer. */
|
||||
; _tx_thread_current_ptr = TX_NULL;
|
||||
;
|
||||
MOV r0, #0 ; NULL value
|
||||
STR r0, [r1] ; Clear current thread pointer
|
||||
;
|
||||
; /* Return to the scheduler. */
|
||||
; _tx_thread_schedule();
|
||||
;
|
||||
CPS #IRQ_MODE ; Enter IRQ mode
|
||||
MRS r1, SPSR ; Get SPSR
|
||||
ORR r1, r1, #SYS_MODE ; Change to SYS Mode
|
||||
BIC r1, r1, #THUMB_MASK ; Clear thumb bit - slarson
|
||||
MSR SPSR_cxsf, r1 ; Put SYS Mode in SPSR
|
||||
LDR lr, =_tx_thread_schedule ; Load scheduler address
|
||||
MOVS pc, lr ; Return to scheduler
|
||||
; }
|
||||
;
|
||||
__tx_thread_idle_system_restore
|
||||
;
|
||||
; /* Just return back to the scheduler! */
|
||||
;
|
||||
LDR lr, =_tx_thread_schedule ; Load scheduler address
|
||||
MOVS pc, lr ; Return to scheduler
|
||||
;}
|
||||
;
|
||||
END
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
EXTERN _tx_thread_system_state
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN __tx_irq_processing_return
|
||||
EXTERN _tx_execution_isr_enter
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_context_save Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_context_save(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_context_save
|
||||
ARM
|
||||
_tx_thread_context_save
|
||||
;
|
||||
; /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
; out, we are in IRQ mode, and all registers are intact. */
|
||||
;
|
||||
; /* Check for a nested interrupt condition. */
|
||||
; if (_tx_thread_system_state++)
|
||||
; {
|
||||
;
|
||||
STMDB sp!, {r0-r3} ; Save some working registers
|
||||
LDR r3, =_tx_thread_system_state ; Pickup address of system state var
|
||||
LDR r2, [r3, #0] ; Pickup system state
|
||||
CMP r2, #0 ; Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save ; Yes, not a nested context save
|
||||
;
|
||||
; /* Nested interrupt condition. */
|
||||
;
|
||||
ADD r2, r2, #1 ; Increment the interrupt counter
|
||||
STR r2, [r3, #0] ; Store it back in the variable
|
||||
;
|
||||
; /* Save the rest of the scratch registers on the stack and return to the
|
||||
; calling ISR. */
|
||||
;
|
||||
MRS r0, SPSR ; Pickup saved SPSR
|
||||
SUB lr, lr, #4 ; Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} ; Store other registers
|
||||
;
|
||||
; /* Return to the ISR. */
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return ; Continue IRQ processing
|
||||
;
|
||||
__tx_thread_not_nested_save
|
||||
; }
|
||||
;
|
||||
; /* Otherwise, not nested, check to see if a thread was running. */
|
||||
; else if (_tx_thread_current_ptr)
|
||||
; {
|
||||
;
|
||||
ADD r2, r2, #1 ; Increment the interrupt counter
|
||||
STR r2, [r3, #0] ; Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] ; Pickup current thread pointer
|
||||
CMP r0, #0 ; Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save ; If so, interrupt occured in
|
||||
; scheduling loop - nothing needs saving!
|
||||
;
|
||||
; /* Save minimal context of interrupted thread. */
|
||||
;
|
||||
MRS r2, SPSR ; Pickup saved SPSR
|
||||
SUB lr, lr, #4 ; Adjust point of interrupt
|
||||
STMDB sp!, {r2, r10, r12, lr} ; Store other registers
|
||||
;
|
||||
; /* Save the current stack pointer in the thread's control block. */
|
||||
; _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
|
||||
;
|
||||
; /* Switch to the system stack. */
|
||||
; sp = _tx_thread_system_stack_ptr;
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return ; Continue IRQ processing
|
||||
;
|
||||
; }
|
||||
; else
|
||||
; {
|
||||
;
|
||||
__tx_thread_idle_system_save
|
||||
;
|
||||
; /* Interrupt occurred in the scheduling loop. */
|
||||
;
|
||||
; /* Not much to do here, just adjust the stack pointer, and return to IRQ
|
||||
; processing. */
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #16 ; Recover saved registers
|
||||
B __tx_irq_processing_return ; Continue IRQ processing
|
||||
;
|
||||
; }
|
||||
;}
|
||||
;
|
||||
|
||||
;
|
||||
;
|
||||
END
|
||||
|
||||
@@ -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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
|
||||
INT_MASK DEFINE 0x80 ; Interrupt bit mask
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_interrupt_control Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_interrupt_control
|
||||
ARM
|
||||
_tx_thread_interrupt_control
|
||||
;
|
||||
; /* Pickup current interrupt lockout posture. */
|
||||
;
|
||||
MRS r3, CPSR ; Pickup current CPSR
|
||||
BIC r1, r3, #INT_MASK ; Clear interrupt lockout bits
|
||||
ORR r1, r1, r0 ; Or-in new interrupt lockout bits
|
||||
;
|
||||
; /* Apply the new interrupt posture. */
|
||||
;
|
||||
MSR CPSR_cxsf, r1 ; Setup new CPSR
|
||||
AND r0, r3, #INT_MASK ; Return previous interrupt mask
|
||||
|
||||
BX lr ; Return to caller
|
||||
;
|
||||
;}
|
||||
;
|
||||
;
|
||||
END
|
||||
@@ -0,0 +1,81 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
;/* */
|
||||
;/* This software is licensed under the Microsoft Software License */
|
||||
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
;/* and in the root directory of this software. */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;/** */
|
||||
;/** ThreadX Component */
|
||||
;/** */
|
||||
;/** Thread */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
DISABLE_INTS DEFINE 0x80 ; IRQ interrupts disabled
|
||||
;
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_interrupt_disable Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;UINT _tx_thread_interrupt_disable(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_interrupt_disable
|
||||
ARM
|
||||
_tx_thread_interrupt_disable??rA
|
||||
_tx_thread_interrupt_disable
|
||||
;
|
||||
; /* Pickup current interrupt lockout posture. */
|
||||
;
|
||||
MRS r0, CPSR ; Pickup current CPSR
|
||||
CPSID i ; Mask interrupts
|
||||
BX lr ; Return to caller
|
||||
;}
|
||||
;
|
||||
;
|
||||
END
|
||||
@@ -0,0 +1,76 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_interrupt_restore Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;void _tx_thread_interrupt_restore(UINT old_posture)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_interrupt_restore
|
||||
ARM
|
||||
_tx_thread_interrupt_restore
|
||||
;
|
||||
; /* Apply the new interrupt posture. */
|
||||
;
|
||||
MSR CPSR_cxsf, r0 ; Setup new CPSR
|
||||
|
||||
BX lr ; Return to caller
|
||||
;}
|
||||
;
|
||||
END
|
||||
@@ -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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
IRQ_MODE DEFINE 0x12 ; IRQ mode
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_irq_nesting_end Cortex-R4/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* William E. Lamie, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function is called by the application from IRQ mode after */
|
||||
;/* _tx_thread_irq_nesting_start has been called and switches the IRQ */
|
||||
;/* processing from system mode back to IRQ mode prior to the ISR */
|
||||
;/* calling _tx_thread_context_restore. Note that this function */
|
||||
;/* assumes the system stack pointer is in the same position after */
|
||||
;/* nesting start function was called. */
|
||||
;/* */
|
||||
;/* This function assumes that the system mode stack pointer was setup */
|
||||
;/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
;/* */
|
||||
;/* This function returns with IRQ interrupts disabled. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* ISRs */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_irq_nesting_end(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_irq_nesting_end
|
||||
ARM
|
||||
_tx_thread_irq_nesting_end
|
||||
MOV r3, lr ; Save ISR return address
|
||||
CPSID i ; Disable interrupts
|
||||
POP {lr} ; Pickup saved lr
|
||||
CPS #IRQ_MODE ; Switch to IRQ mode
|
||||
MOV pc, r3 ; Return to ISR
|
||||
;}
|
||||
;
|
||||
;
|
||||
END
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
SYS_MODE DEFINE 0x1F ; System mode
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_irq_nesting_start Cortex-R4/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* William E. Lamie, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function is called by the application from IRQ mode after */
|
||||
;/* _tx_thread_context_save has been called and switches the IRQ */
|
||||
;/* processing to the system mode so nested IRQ interrupt processing */
|
||||
;/* is possible (system mode has its own "lr" register). Note that */
|
||||
;/* this function assumes that the system mode stack pointer was setup */
|
||||
;/* during low-level initialization (tx_initialize_low_level.s). */
|
||||
;/* */
|
||||
;/* This function returns with IRQ interrupts enabled. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* ISRs */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_irq_nesting_start(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_irq_nesting_start
|
||||
ARM
|
||||
_tx_thread_irq_nesting_start
|
||||
MOV r3, lr ; Save ISR return address
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
PUSH {lr} ; Save system mode lr on the system mode stack
|
||||
CPSIE i ; Enable interrupts
|
||||
MOV pc, r3 ; Return to ISR
|
||||
;}
|
||||
;
|
||||
;
|
||||
END
|
||||
|
||||
@@ -0,0 +1,443 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
EXTERN _tx_thread_execute_ptr
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_execution_thread_enter
|
||||
;
|
||||
IMPORT _txm_system_mode_enter
|
||||
IMPORT _txm_system_mode_exit
|
||||
;
|
||||
THUMB_MASK EQU 0x20 ; Thumb bit (5) of CPSR/SPSR.
|
||||
IRQ_MODE EQU 0x12 ; IRQ mode
|
||||
USR_MODE EQU 0x10 ; USR mode
|
||||
SVC_MODE EQU 0x13 ; SVC mode
|
||||
SYS_MODE EQU 0x1F ; SYS mode
|
||||
MODE_MASK EQU 0x1F ; Mode mask
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_schedule Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function waits for a thread control block pointer to appear in */
|
||||
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
;/* in the variable, the corresponding thread is resumed. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
;/* _tx_thread_system_return Return to system from thread */
|
||||
;/* _tx_thread_context_restore Restore thread's context */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_schedule(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_schedule
|
||||
ARM
|
||||
_tx_thread_schedule??rA
|
||||
_tx_thread_schedule
|
||||
|
||||
; Enter the scheduler.
|
||||
SVC 0
|
||||
|
||||
; We should never get here - ever!
|
||||
_tx_scheduler_fault__
|
||||
B _tx_scheduler_fault__
|
||||
;}
|
||||
; ****************************************************************************
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SWI_Handler
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC SWI_Handler
|
||||
ARM
|
||||
SWI_Handler
|
||||
|
||||
STMFD sp!, {r0-r3, r12, lr} ; Store the registers
|
||||
MOV r1, sp ; Set pointer to parameters
|
||||
MRS r0, spsr ; Get spsr
|
||||
STMFD sp!, {r0, r3} ; Store spsr onto stack and another
|
||||
; register to maintain 8-byte-aligned stack
|
||||
TST r0, #THUMB_MASK ; Occurred in Thumb state?
|
||||
LDRNEH r0, [lr,#-2] ; Yes: Load halfword and...
|
||||
BICNE r0, r0, #0xFF00 ; ...extract comment field
|
||||
LDREQ r0, [lr,#-4] ; No: Load word and...
|
||||
BICEQ r0, r0, #0xFF000000 ; ...extract comment field
|
||||
|
||||
; r0 now contains SVC number
|
||||
; r1 now contains pointer to stacked registers
|
||||
|
||||
;
|
||||
; The service call is handled here
|
||||
;
|
||||
|
||||
CMP r0, #0 ; Is it a schedule request?
|
||||
BEQ _tx_handler_svc_schedule ; Yes, go there
|
||||
|
||||
CMP r0, #1 ; Is it a system mode enter request?
|
||||
BEQ _tx_handler_svc_super_enter ; Yes, go there
|
||||
|
||||
CMP r0, #2 ; Is it a system mode exit request?
|
||||
BEQ _tx_handler_svc_super_exit ; Yes, go there
|
||||
|
||||
LDR r2, =0x123456
|
||||
CMP r0, r2 ; Is it an ARM request?
|
||||
BEQ _tx_handler_svc_arm ; Yes, go there
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Unknown SVC argument
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Unrecognized service call
|
||||
_tx_handler_svc_unrecognized
|
||||
|
||||
_tx_handler_svc_unrecognized_loop ; We should never get here
|
||||
B _tx_handler_svc_unrecognized_loop
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SVC 1
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; At this point we have an SVC 1, which means we are entering
|
||||
; supervisor mode to service a kernel call.
|
||||
_tx_handler_svc_super_enter
|
||||
; Make sure that we have been called from the system mode enter location (security)
|
||||
LDR r2, =_txm_system_mode_enter ; Load the address of the known call point
|
||||
SUB r1, lr, #4 ; Calculate the address of the actual call
|
||||
CMP r1, r2 ; Did we come from txm_module_manager_user_mode_entry?
|
||||
BNE _tx_handler_svc_unrecognized ; Return to where we came
|
||||
|
||||
; Clear the user mode flag in the thread structure
|
||||
LDR r1, =_tx_thread_current_ptr ; Load the current thread pointer address
|
||||
LDR r2, [r1] ; Load current thread location from the pointer (pointer indirection)
|
||||
MOV r1, #0 ; Load the new user mode flag value (user mode flag clear -> not user mode -> system)
|
||||
STR r1, [r2, #0x9C] ; Clear the current user mode selection for thread
|
||||
|
||||
; Now we enter the system mode and return
|
||||
LDMFD sp!, {r0, r3} ; Get spsr from the stack
|
||||
BIC r0, r0, #MODE_MASK ; clear mode field
|
||||
ORR r0, r0, #SYS_MODE ; system mode code
|
||||
MSR SPSR_cxsf, r0 ; Restore the spsr
|
||||
|
||||
LDR r1, [r2, #0xA8] ; Load the module kernel stack pointer
|
||||
CPS #SYS_MODE ; Switch to SYS mode
|
||||
MOV r3, sp ; Grab thread stack pointer
|
||||
MOV sp, r1 ; Set SP to kernel stack pointer
|
||||
CPS #SVC_MODE ; Switch back to SVC mode
|
||||
STR r3, [r2, #0xB0] ; Save thread stack pointer
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r3, [r2, #0xAC] ; Load the module kernel stack size
|
||||
STR r3, [r2, #20] ; Set stack size
|
||||
LDRD r0, r1, [r2, #0xA4] ; Load the module kernel stack start and end
|
||||
STRD r0, r1, [r2, #0x0C] ; Set stack start and end
|
||||
#endif
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ ; Restore the registers and return
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SVC 2
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; At this point we have an SVC 2, which means we are exiting
|
||||
; supervisor mode after servicing a kernel call.
|
||||
_tx_handler_svc_super_exit
|
||||
; Make sure that we have been called from the system mode exit location (security)
|
||||
LDR r2, =_txm_system_mode_exit ; Load the address of the known call point
|
||||
SUB r1, lr, #4 ; Calculate the address of the actual call
|
||||
CMP r1, r2 ; Did we come from txm_module_manager_user_mode_entry?
|
||||
BNE _tx_handler_svc_unrecognized ; Return to where we came
|
||||
|
||||
; Set the user mode flag into the thread structure
|
||||
LDR r1, =_tx_thread_current_ptr ; Load the current thread pointer address
|
||||
LDR r2, [r1] ; Load the current thread location from the pointer (pointer indirection)
|
||||
MOV r1, #1 ; Load the new user mode flag value (user mode enabled -> not system anymore)
|
||||
STR r1, [r2, #0x9C] ; Clear the current user mode selection for thread
|
||||
|
||||
; Now we enter user mode (exit the system mode) and return
|
||||
LDMFD sp!, {r0, r3} ; Get spsr from the stack
|
||||
BIC r0, r0, #MODE_MASK ; clear mode field
|
||||
ORR r0, r0, #USR_MODE ; user mode code
|
||||
MSR SPSR_cxsf, r0 ; Restore the spsr
|
||||
|
||||
LDR r1, [r2, #0xB0] ; Load the module thread stack pointer
|
||||
CPS #SYS_MODE ; Switch to SYS mode
|
||||
MOV sp, r1 ; Set SP back to thread stack pointer
|
||||
CPS #SVC_MODE ; Switch back to SVC mode
|
||||
#ifndef TXM_MODULE_KERNEL_STACK_MAINTENANCE_DISABLE
|
||||
LDR r3, [r2, #0xBC] ; Load the module thread stack size
|
||||
STR r3, [r2, #20] ; Set stack size
|
||||
LDRD r0, r1, [r2, #0xB4] ; Load the module thread stack start and end
|
||||
STRD r0, r1, [r2, #0x0C] ; Set stack start and end
|
||||
#endif
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ ; Restore the registers and return
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ARM Semihosting
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
_tx_handler_svc_arm
|
||||
|
||||
; *** TODO: handle semihosting requests or ARM angel requests ***
|
||||
|
||||
; just return
|
||||
LDMFD sp!, {r0, r3} ; Get spsr from the stack
|
||||
MSR SPSR_cxsf, r0 ; Restore the spsr
|
||||
LDMFD sp!, {r0-r3, r12, pc}^ ; Restore the registers and return
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SVC 0
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; At this point we have an SVC 0: enter the scheduler.
|
||||
_tx_handler_svc_schedule
|
||||
|
||||
LDMFD sp!, {r0, r3} ; Get spsr from stack
|
||||
MSR SPSR_cxsf, r0 ; Restore spsr
|
||||
LDMFD sp!, {r0-r3, r12, lr} ; Restore the registers
|
||||
|
||||
; This code 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.
|
||||
;
|
||||
; /* Enable interrupts. */
|
||||
;
|
||||
CPSIE i ; Enable IRQ interrupts
|
||||
|
||||
;
|
||||
; /* Wait for a thread to execute. */
|
||||
; do
|
||||
; {
|
||||
LDR r1, =_tx_thread_execute_ptr ; Address of thread execute ptr
|
||||
;
|
||||
__tx_thread_schedule_loop
|
||||
LDR r0, [r1, #0] ; Pickup next thread to execute
|
||||
CMP r0, #0 ; Is it NULL?
|
||||
BEQ __tx_thread_schedule_loop ; If so, keep looking for a thread
|
||||
;
|
||||
; }
|
||||
; while(_tx_thread_execute_ptr == TX_NULL);
|
||||
;
|
||||
; /* Yes! We have a thread to execute. Lockout interrupts and
|
||||
; transfer control to it. */
|
||||
;
|
||||
CPSID i ; Disable interrupts
|
||||
;
|
||||
; /* Setup the current thread pointer. */
|
||||
; _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
;
|
||||
LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread
|
||||
STR r0, [r1, #0] ; Setup current thread pointer
|
||||
;
|
||||
; /* Increment the run count for this thread. */
|
||||
; _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
;
|
||||
LDR r2, [r0, #4] ; Pickup run counter
|
||||
LDR r3, [r0, #24] ; Pickup time-slice for this thread
|
||||
ADD r2, r2, #1 ; Increment thread run-counter
|
||||
STR r2, [r0, #4] ; Store the new run counter
|
||||
;
|
||||
; /* Setup time-slice, if present. */
|
||||
; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
;
|
||||
LDR r2, =_tx_timer_time_slice ; Pickup address of time slice variable
|
||||
STR r3, [r2, #0] ; Setup time-slice
|
||||
;
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the thread entry function to indicate the thread is executing. */
|
||||
;
|
||||
MOV r5, r0 ; Save r0
|
||||
BL _tx_execution_thread_enter ; Call the thread execution enter function
|
||||
MOV r0, r5 ; Restore r0
|
||||
#endif
|
||||
|
||||
; Determine if an interrupt frame or a synchronous task suspension frame is present.
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
LDR sp, [r0, #8] ; Switch to thread stack pointer
|
||||
LDMIA sp!, {r4, r5} ; Pickup the stack type and saved CPSR
|
||||
CPS #SVC_MODE ; Enter SVC mode
|
||||
|
||||
; **************************************************************************
|
||||
; Set up MPU for module.
|
||||
LDR r1, [r0, #0x94] ; Pickup module instance pointer
|
||||
CMP r1, #0 ; Valid module pointer?
|
||||
BEQ _tx_end_mpu_update ; No - skip memory protection setup
|
||||
LDR r2, [r0, #0xA0] ; Pickup tx_thread_module_user_mode
|
||||
CMP r2, #1 ; In user mode?
|
||||
BNE _tx_end_mpu_update ; No - skip memory protection setup
|
||||
; Is the MPU already set up for this module?
|
||||
; Pickup the first data entry to check (txm_module_instance_mpu_registers[5])
|
||||
LDR r2, [r1, #0xA0] ; Pickup txm_module_instance_mpu_registers[5]
|
||||
MOV r3, #5 ; Select region 5
|
||||
MCR p15, 0, r3, c6, c2, 0 ; Select region 5
|
||||
MRC p15, 0, r3, c6, c1, 0 ; Read DRBAR into r3
|
||||
CMP r2, r3 ; Is module already loaded?
|
||||
BEQ _tx_end_mpu_update ; Yes - skip memory protection setup
|
||||
|
||||
; Disable MPU before applying new regions.
|
||||
MRC p15, 0, r2, c1, c0, 0 ; Read SCTLR
|
||||
BIC r2, r2, #1 ; Disable MPU
|
||||
DSB
|
||||
MCR p15, 0, r2, c1, c0, 0 ; Write to SCTLR
|
||||
ISB
|
||||
; Loop to load MPU registers
|
||||
MOV r3, #0 ; Loop index
|
||||
ADD r1, r1, #0x64 ; Build address of MPU register table
|
||||
_tx_mpu_loop
|
||||
LDR r2, [r1] ; Pickup txm_module_mpu_region_address
|
||||
MCR p15, 0, r3, c6, c2, 0 ; Select region
|
||||
MCR p15, 0, r2, c6, c1, 0 ; Write to DRBAR
|
||||
ADD r1, r1, #4 ; Increment to next MPU parameter
|
||||
LDR r2, [r1] ; Pickup txm_module_mpu_region_size
|
||||
MCR p15, 0, r2, c6, c1, 2 ; Write to DRSR
|
||||
ADD r1, r1, #4 ; Increment to next MPU parameter
|
||||
LDR r2, [r1] ; Pickup txm_module_mpu_region_attributes
|
||||
MCR p15, 0, r2, c6, c1, 4 ; Write to DRACR
|
||||
ADD r1, r1, #4 ; Increment to next MPU parameter
|
||||
ADD r3, r3, #1 ; Increment loop index
|
||||
CMP r3, #0xB ; Check the limit
|
||||
BLE _tx_mpu_loop ; Loop if not finished
|
||||
|
||||
; Enable MPU with new regions.
|
||||
MRC p15, 0, r2, c1, c0, 0 ; Read SCTLR
|
||||
ORR r2, r2, #1 ; Enable MPU
|
||||
ORR r2, r2, #0x20000 ; Enable Background Region
|
||||
DSB
|
||||
MCR p15, 0, r2, c1, c0, 0 ; Write to SCTLR
|
||||
ISB
|
||||
;
|
||||
_tx_end_mpu_update
|
||||
; **************************************************************************
|
||||
|
||||
CMP r4, #0 ; Check for synchronous context switch
|
||||
BEQ _tx_solicited_return
|
||||
|
||||
MSR SPSR_cxsf, r5 ; Setup SPSR for return
|
||||
LDR r1, [r0, #8] ; Get thread SP
|
||||
LDR lr, [r1, #0x40] ; Get thread PC
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
LDR r2, [r0, #144] ; Pickup the VFP enabled flag
|
||||
CMP r2, #0 ; Is the VFP enabled?
|
||||
BEQ _tx_skip_interrupt_vfp_restore ; No, skip VFP interrupt restore
|
||||
VLDMIA sp!, {D0-D15} ; Recover D0-D15
|
||||
LDR r4, [sp], #4 ; Pickup FPSCR
|
||||
VMSR FPSCR, r4 ; Restore FPSCR
|
||||
CPS #SVC_MODE ; Enter SVC mode
|
||||
LDR lr, [r1, #0x144] ; Get thread PC
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
_tx_skip_interrupt_vfp_restore
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r0-r12, lr} ; Restore registers
|
||||
ADD sp, sp, #4 ; Fix stack pointer
|
||||
CPS #SVC_MODE ; Enter SVC mode
|
||||
SUBS pc, lr, #0 ; Return to point of thread interrupt
|
||||
|
||||
_tx_solicited_return
|
||||
MOV r2, r5 ; Move CPSR to scratch register
|
||||
CPS #SYS_MODE ; Enter SYS mode
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
LDR r1, [r0, #144] ; Pickup the VFP enabled flag
|
||||
CMP r1, #0 ; Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_restore ; No, skip VFP solicited restore
|
||||
VLDMIA sp!, {D8-D15} ; Recover D8-D15
|
||||
LDR r4, [sp], #4 ; Pickup FPSCR
|
||||
VMSR FPSCR, r4 ; Restore FPSCR
|
||||
_tx_skip_solicited_vfp_restore
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r4-r11, lr} ; Restore registers
|
||||
MOV r1, lr ; Copy lr to r1 to preserve across mode change
|
||||
CPS #SVC_MODE ; Enter SVC mode
|
||||
MSR SPSR_cxsf, r2 ; Recover CPSR
|
||||
SUBS pc, r1, #0 ; Return to thread synchronously
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; End SWI_Handler
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
PUBLIC tx_thread_vfp_enable
|
||||
CODE32
|
||||
tx_thread_vfp_enable??rA
|
||||
tx_thread_vfp_enable
|
||||
MRS r2, CPSR ; Pickup the CPSR
|
||||
CPSID i ; Disable IRQ interrupts
|
||||
LDR r0, =_tx_thread_current_ptr ; Build current thread pointer address
|
||||
LDR r1, [r0] ; Pickup current thread pointer
|
||||
CMP r1, #0 ; Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_enable ; If NULL, skip VFP enable
|
||||
MOV r0, #1 ; Build enable value
|
||||
STR r0, [r1, #144] ; Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_enable:
|
||||
MSR CPSR_cxsf, r2 ; Recover CPSR
|
||||
BX LR ; Return to caller
|
||||
|
||||
PUBLIC tx_thread_vfp_disable
|
||||
CODE32
|
||||
tx_thread_vfp_disable??rA
|
||||
tx_thread_vfp_disable
|
||||
MRS r2, CPSR ; Pickup the CPSR
|
||||
CPSID i ; Disable IRQ interrupts
|
||||
LDR r0, =_tx_thread_current_ptr ; Build current thread pointer address
|
||||
LDR r1, [r0] ; Pickup current thread pointer
|
||||
CMP r1, #0 ; Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_disable ; If NULL, skip VFP disable
|
||||
MOV r0, #0 ; Build disable value
|
||||
STR r0, [r1, #144] ; Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_disable:
|
||||
MSR CPSR_cxsf, r2 ; Recover CPSR
|
||||
BX LR ; Return to caller
|
||||
#endif
|
||||
|
||||
END
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
SYS_MODE DEFINE 0x1F ; SYS mode
|
||||
CPSR_MASK DEFINE 0x9F ; Mask initial CPSR, IRQ ints enabled
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_stack_build Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function builds a stack frame on the supplied thread's stack. */
|
||||
;/* The stack frame results in a fake interrupt return to the supplied */
|
||||
;/* function pointer. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* thread_ptr Pointer to thread control blk */
|
||||
;/* function_ptr Pointer to return function */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* _tx_thread_create Create thread service */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_stack_build
|
||||
|
||||
ARM
|
||||
_tx_thread_stack_build
|
||||
;
|
||||
;
|
||||
; /* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
; on the Cortex-R4 should look like the following after it is built:
|
||||
;
|
||||
; Stack Top: 1 Interrupt stack frame type
|
||||
; CPSR Initial value for CPSR
|
||||
; a1 (r0) Initial value for a1
|
||||
; a2 (r1) Initial value for a2
|
||||
; a3 (r2) Initial value for a3
|
||||
; a4 (r3) Initial value for a4
|
||||
; v1 (r4) Initial value for v1
|
||||
; v2 (r5) Initial value for v2
|
||||
; v3 (r6) Initial value for v3
|
||||
; v4 (r7) Initial value for v4
|
||||
; v5 (r8) Initial value for v5
|
||||
; sb (r9) Initial value for sb
|
||||
; sl (r10) Initial value for sl
|
||||
; fp (r11) Initial value for fp
|
||||
; ip (r12) Initial value for ip
|
||||
; lr (r14) Initial value for lr
|
||||
; pc (r15) Initial value for pc
|
||||
; 0 For stack backtracing
|
||||
;
|
||||
; Stack Bottom: (higher memory address) */
|
||||
;
|
||||
LDR r2, [r0, #16] ; Pickup end of stack area
|
||||
BIC r2, r2, #7 ; Ensure 8-byte alignment
|
||||
SUB r2, r2, #76 ; Allocate space for the stack frame
|
||||
;
|
||||
; /* Actually build the stack frame. */
|
||||
;
|
||||
MOV r3, #1 ; Build interrupt stack type
|
||||
STR r3, [r2, #0] ; Store stack type
|
||||
MOV r3, #0 ; Build initial register value
|
||||
STR r3, [r2, #8] ; Store initial r0
|
||||
STR r3, [r2, #12] ; Store initial r1
|
||||
STR r3, [r2, #16] ; Store initial r2
|
||||
STR r3, [r2, #20] ; Store initial r3
|
||||
STR r3, [r2, #24] ; Store initial r4
|
||||
STR r3, [r2, #28] ; Store initial r5
|
||||
STR r3, [r2, #32] ; Store initial r6
|
||||
STR r3, [r2, #36] ; Store initial r7
|
||||
STR r3, [r2, #40] ; Store initial r8
|
||||
STR r3, [r2, #44] ; Store initial r9
|
||||
LDR r3, [r0, #12] ; Pickup stack starting address
|
||||
STR r3, [r2, #48] ; Store initial r10 (sl)
|
||||
MOV r3, #0 ; Build initial register value
|
||||
STR r3, [r2, #52] ; Store initial r11
|
||||
STR r3, [r2, #56] ; Store initial r12
|
||||
STR r3, [r2, #60] ; Store initial lr
|
||||
STR r1, [r2, #64] ; Store initial pc
|
||||
STR r3, [r2, #68] ; 0 for back-trace
|
||||
MRS r1, CPSR ; Pickup CPSR
|
||||
BIC r1, r1, #CPSR_MASK ; Mask mode bits of CPSR
|
||||
ORR r3, r1, #SYS_MODE ; Build CPSR, SYS mode, interrupts enabled
|
||||
STR r3, [r2, #4] ; Store initial CPSR
|
||||
;
|
||||
; /* Setup stack pointer. */
|
||||
; thread_ptr -> tx_thread_stack_ptr = r2;
|
||||
;
|
||||
STR r2, [r0, #8] ; Save stack pointer in thread's
|
||||
; control block
|
||||
|
||||
BX lr ; Return to caller
|
||||
;}
|
||||
END
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_thread_schedule
|
||||
EXTERN _tx_execution_thread_exit
|
||||
;
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_system_return Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_system_return(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_system_return
|
||||
ARM
|
||||
_tx_thread_system_return??rA
|
||||
_tx_thread_system_return
|
||||
;
|
||||
; /* Lockout interrupts. */
|
||||
;
|
||||
MRS r1, CPSR ; Pickup the CPSR
|
||||
CPSID i ; Disable interrupts
|
||||
; /* Save minimal context on the stack. */
|
||||
;
|
||||
STMDB sp!, {r4-r11, lr} ; Save minimal context
|
||||
LDR r5, =_tx_thread_current_ptr ; Pickup address of current ptr
|
||||
LDR r6, [r5, #0] ; Pickup current thread pointer
|
||||
|
||||
#ifdef __ARMVFP__
|
||||
LDR r0, [r6, #144] ; Pickup the VFP enabled flag
|
||||
CMP r0, #0 ; Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_save ; No, skip VFP solicited save
|
||||
VMRS r4, FPSCR ; Pickup the FPSCR
|
||||
STR r4, [sp, #-4]! ; Save FPSCR
|
||||
VSTMDB sp!, {D8-D15} ; Save D8-D15
|
||||
_tx_skip_solicited_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r0, #0 ; Build a solicited stack type
|
||||
STMDB sp!, {r0-r1} ; Save type and CPSR
|
||||
;
|
||||
;
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
;
|
||||
BL _tx_execution_thread_exit ; Call the thread exit function
|
||||
#endif
|
||||
|
||||
LDR r2, =_tx_timer_time_slice ; Pickup address of time slice
|
||||
LDR r1, [r2, #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;
|
||||
;
|
||||
STR sp, [r6, #8] ; Save thread stack pointer
|
||||
;
|
||||
; /* Determine if the time-slice is active. */
|
||||
; if (_tx_timer_time_slice)
|
||||
; {
|
||||
;
|
||||
MOV r4, #0 ; Build clear value
|
||||
CMP r1, #0 ; Is a time-slice active?
|
||||
BEQ __tx_thread_dont_save_ts ; No, don't save the time-slice
|
||||
;
|
||||
; /* Save time-slice for the thread and clear the current time-slice. */
|
||||
; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
; _tx_timer_time_slice = 0;
|
||||
;
|
||||
STR r4, [r2, #0] ; Clear time-slice
|
||||
STR r1, [r6, #24] ; Save current time-slice
|
||||
;
|
||||
; }
|
||||
__tx_thread_dont_save_ts
|
||||
;
|
||||
; /* Clear the current thread pointer. */
|
||||
; _tx_thread_current_ptr = TX_NULL;
|
||||
;
|
||||
STR r4, [r5, #0] ; Clear current thread pointer
|
||||
B _tx_thread_schedule ; Jump to scheduler!
|
||||
;
|
||||
;}
|
||||
END
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
EXTERN _tx_thread_system_state
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _tx_execution_isr_enter
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_thread_vectored_context_save Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_thread_vectored_context_save(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_thread_vectored_context_save
|
||||
ARM
|
||||
_tx_thread_vectored_context_save
|
||||
;
|
||||
; /* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
; out, we are in IRQ mode, the minimal context is already saved, and the
|
||||
; lr register contains the return ISR address. */
|
||||
;
|
||||
; /* Check for a nested interrupt condition. */
|
||||
; if (_tx_thread_system_state++)
|
||||
; {
|
||||
;
|
||||
LDR r3, =_tx_thread_system_state ; Pickup address of system state var
|
||||
LDR r2, [r3, #0] ; Pickup system state
|
||||
CMP r2, #0 ; Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save ; Yes, not a nested context save
|
||||
;
|
||||
; /* Nested interrupt condition. */
|
||||
;
|
||||
ADD r2, r2, #1 ; Increment the interrupt counter
|
||||
STR r2, [r3, #0] ; Store it back in the variable
|
||||
;
|
||||
; /* Note: Minimal context of interrupted thread is already saved. */
|
||||
;
|
||||
; /* Return to the ISR. */
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
BX lr ; Return to caller
|
||||
;
|
||||
__tx_thread_not_nested_save
|
||||
; }
|
||||
;
|
||||
; /* Otherwise, not nested, check to see if a thread was running. */
|
||||
; else if (_tx_thread_current_ptr)
|
||||
; {
|
||||
;
|
||||
ADD r2, r2, #1 ; Increment the interrupt counter
|
||||
STR r2, [r3, #0] ; Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread ptr
|
||||
LDR r0, [r1, #0] ; Pickup current thread pointer
|
||||
CMP r0, #0 ; Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save ; If so, interrupt occured in
|
||||
; scheduling loop - nothing needs saving!
|
||||
;
|
||||
; /* Note: Minimal context of interrupted thread is already saved. */
|
||||
;
|
||||
; /* Save the current stack pointer in the thread's control block. */
|
||||
; _tx_thread_current_ptr -> tx_stack_ptr = sp;
|
||||
;
|
||||
; /* Switch to the system stack. */
|
||||
; sp = _tx_thread_system_stack_ptr;
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
BX lr ; 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. */
|
||||
;
|
||||
MOV r10, #0 ; Clear stack limit
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
;
|
||||
; /* Call the ISR enter function to indicate an ISR is executing. */
|
||||
;
|
||||
PUSH {lr} ; Save ISR lr
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
POP {lr} ; Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #32 ; Recover saved registers
|
||||
MOV pc, lr ; Return to caller
|
||||
;
|
||||
; }
|
||||
;}
|
||||
END
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 Assembly language external references...
|
||||
;
|
||||
EXTERN _tx_timer_time_slice
|
||||
EXTERN _tx_timer_system_clock
|
||||
EXTERN _tx_timer_current_ptr
|
||||
EXTERN _tx_timer_list_start
|
||||
EXTERN _tx_timer_list_end
|
||||
EXTERN _tx_timer_expired_time_slice
|
||||
EXTERN _tx_timer_expired
|
||||
EXTERN _tx_thread_time_slice
|
||||
EXTERN _tx_timer_expiration_process
|
||||
;
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _tx_timer_interrupt Cortex-R4/IAR */
|
||||
;/* 6.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 */
|
||||
;/* */
|
||||
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _tx_timer_interrupt(VOID)
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _tx_timer_interrupt
|
||||
ARM
|
||||
_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 r1, =_tx_timer_system_clock ; Pickup address of system clock
|
||||
LDR r0, [r1, #0] ; Pickup system clock
|
||||
ADD r0, r0, #1 ; Increment system clock
|
||||
STR r0, [r1, #0] ; Store new system clock
|
||||
;
|
||||
; /* Test for time-slice expiration. */
|
||||
; if (_tx_timer_time_slice)
|
||||
; {
|
||||
;
|
||||
LDR r3, =_tx_timer_time_slice ; Pickup address of time-slice
|
||||
LDR r2, [r3, #0] ; Pickup time-slice
|
||||
CMP r2, #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 r2, r2, #1 ; Decrement the time-slice
|
||||
STR r2, [r3, #0] ; Store new time-slice value
|
||||
;
|
||||
; /* Check for expiration. */
|
||||
; if (__tx_timer_time_slice == 0)
|
||||
;
|
||||
CMP r2, #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 r3, =_tx_timer_expired_time_slice ; Pickup address of expired flag
|
||||
MOV r0, #1 ; Build expired value
|
||||
STR r0, [r3, #0] ; Set time-slice expiration flag
|
||||
;
|
||||
; }
|
||||
;
|
||||
__tx_timer_no_time_slice
|
||||
;
|
||||
; /* Test for timer expiration. */
|
||||
; if (*_tx_timer_current_ptr)
|
||||
; {
|
||||
;
|
||||
LDR r1, =_tx_timer_current_ptr ; Pickup current timer pointer addr
|
||||
LDR r0, [r1, #0] ; Pickup current timer
|
||||
LDR r2, [r0, #0] ; Pickup timer list entry
|
||||
CMP r2, #0 ; Is there anything in the list?
|
||||
BEQ __tx_timer_no_timer ; No, just increment the timer
|
||||
;
|
||||
; /* Set expiration flag. */
|
||||
; _tx_timer_expired = TX_TRUE;
|
||||
;
|
||||
LDR r3, =_tx_timer_expired ; Pickup expiration flag address
|
||||
MOV r2, #1 ; Build expired value
|
||||
STR r2, [r3, #0] ; Set expired flag
|
||||
B __tx_timer_done ; Finished timer processing
|
||||
;
|
||||
; }
|
||||
; else
|
||||
; {
|
||||
__tx_timer_no_timer
|
||||
;
|
||||
; /* No timer expired, increment the timer pointer. */
|
||||
; _tx_timer_current_ptr++;
|
||||
;
|
||||
ADD r0, r0, #4 ; Move to next timer
|
||||
;
|
||||
; /* Check for wrap-around. */
|
||||
; if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
;
|
||||
LDR r3, =_tx_timer_list_end ; Pickup addr of timer list end
|
||||
LDR r2, [r3, #0] ; Pickup list end
|
||||
CMP r0, r2 ; Are we at list end?
|
||||
BNE __tx_timer_skip_wrap ; No, skip wrap-around logic
|
||||
;
|
||||
; /* Wrap to beginning of list. */
|
||||
; _tx_timer_current_ptr = _tx_timer_list_start;
|
||||
;
|
||||
LDR r3, =_tx_timer_list_start ; Pickup addr of timer list start
|
||||
LDR r0, [r3, #0] ; Set current pointer to list start
|
||||
;
|
||||
__tx_timer_skip_wrap
|
||||
;
|
||||
STR r0, [r1, #0] ; Store new current timer pointer
|
||||
; }
|
||||
;
|
||||
__tx_timer_done
|
||||
;
|
||||
;
|
||||
; /* See if anything has expired. */
|
||||
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
; {
|
||||
;
|
||||
LDR r3, =_tx_timer_expired_time_slice ; Pickup addr of expired flag
|
||||
LDR r2, [r3, #0] ; Pickup time-slice expired flag
|
||||
CMP r2, #0 ; Did a time-slice expire?
|
||||
BNE __tx_something_expired ; If non-zero, time-slice expired
|
||||
LDR r1, =_tx_timer_expired ; Pickup addr of other expired flag
|
||||
LDR r0, [r1, #0] ; Pickup timer expired flag
|
||||
CMP r0, #0 ; Did a timer expire?
|
||||
BEQ __tx_timer_nothing_expired ; No, nothing expired
|
||||
;
|
||||
__tx_something_expired
|
||||
;
|
||||
;
|
||||
STMDB sp!, {r0, lr} ; Save the lr register on the stack
|
||||
; and save r0 just to keep 8-byte alignment
|
||||
;
|
||||
; /* Did a timer expire? */
|
||||
; if (_tx_timer_expired)
|
||||
; {
|
||||
;
|
||||
LDR r1, =_tx_timer_expired ; Pickup addr of expired flag
|
||||
LDR r0, [r1, #0] ; Pickup timer expired flag
|
||||
CMP r0, #0 ; Check for timer expiration
|
||||
BEQ __tx_timer_dont_activate ; If not set, skip timer activation
|
||||
;
|
||||
; /* Process timer expiration. */
|
||||
; _tx_timer_expiration_process();
|
||||
;
|
||||
BL _tx_timer_expiration_process ; Call the timer expiration handling routine
|
||||
;
|
||||
; }
|
||||
__tx_timer_dont_activate
|
||||
;
|
||||
; /* Did time slice expire? */
|
||||
; if (_tx_timer_expired_time_slice)
|
||||
; {
|
||||
;
|
||||
LDR r3, =_tx_timer_expired_time_slice ; Pickup addr of time-slice expired
|
||||
LDR r2, [r3, #0] ; Pickup the actual flag
|
||||
CMP r2, #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
|
||||
;
|
||||
;
|
||||
LDMIA sp!, {r0, lr} ; Recover lr register (r0 is just there for
|
||||
; the 8-byte stack alignment
|
||||
;
|
||||
; }
|
||||
;
|
||||
__tx_timer_nothing_expired
|
||||
;
|
||||
BX lr ; Return to caller
|
||||
;
|
||||
;}
|
||||
END
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_power_of_two_block_size Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates a power of two size at or immediately above*/
|
||||
/* the input size and returns it to the caller. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* size Block size */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* calculated size Rounded up to power of two */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_alignment_adjust Adjust alignment for Cortex-R */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_power_of_two_block_size(ULONG size)
|
||||
{
|
||||
/* Check for 0 size. */
|
||||
if(size == 0)
|
||||
return 0;
|
||||
|
||||
/* Minimum MPU block size is 32. */
|
||||
if(size <= 32)
|
||||
return 32;
|
||||
|
||||
/* Bit twiddling trick to round to next high power of 2
|
||||
(if original size is power of 2, it will return original size. Perfect!) */
|
||||
size--;
|
||||
size |= size >> 1;
|
||||
size |= size >> 2;
|
||||
size |= size >> 4;
|
||||
size |= size >> 8;
|
||||
size |= size >> 16;
|
||||
size++;
|
||||
|
||||
/* Return a power of 2 size at or above the input size. */
|
||||
return(size);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_alignment_adjust Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function adjusts the alignment and size of the code and data */
|
||||
/* section for a given module implementation. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_preamble Pointer to module preamble */
|
||||
/* code_size Size of the code area (updated) */
|
||||
/* code_alignment Code area alignment (updated) */
|
||||
/* data_size Size of data area (updated) */
|
||||
/* data_alignment Data area alignment (updated) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_power_of_two_block_size Calculate power of two size */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Initial thread stack frame */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble,
|
||||
ULONG *code_size,
|
||||
ULONG *code_alignment,
|
||||
ULONG *data_size,
|
||||
ULONG *data_alignment)
|
||||
{
|
||||
|
||||
ULONG local_code_size;
|
||||
ULONG local_code_alignment;
|
||||
ULONG local_data_size;
|
||||
ULONG local_data_alignment;
|
||||
ULONG code_size_accum;
|
||||
ULONG data_size_accum;
|
||||
|
||||
/* Copy the input parameters into local variables for ease of use. */
|
||||
local_code_size = *code_size;
|
||||
local_code_alignment = *code_alignment;
|
||||
local_data_size = *data_size;
|
||||
local_data_alignment = *data_alignment;
|
||||
|
||||
/* Determine code block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU code entries available. The following is how the code size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
local_code_alignment = _txm_power_of_two_block_size(local_code_size) >> 2;
|
||||
code_size_accum = local_code_alignment + local_code_alignment;
|
||||
code_size_accum = code_size_accum + (_txm_power_of_two_block_size(local_code_size - code_size_accum) >> 1);
|
||||
code_size_accum = code_size_accum + _txm_power_of_two_block_size(local_code_size - code_size_accum);
|
||||
local_code_size = code_size_accum;
|
||||
|
||||
/* Determine data block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU data entries available. The following is how the data size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
local_data_alignment = _txm_power_of_two_block_size(local_data_size) >> 2;
|
||||
data_size_accum = local_data_alignment + local_data_alignment;
|
||||
data_size_accum = data_size_accum + (_txm_power_of_two_block_size(local_data_size - data_size_accum) >> 1);
|
||||
data_size_accum = data_size_accum + _txm_power_of_two_block_size(local_data_size - data_size_accum);
|
||||
local_data_size = data_size_accum;
|
||||
|
||||
/* Return all the information to the caller. */
|
||||
*code_size = local_code_size;
|
||||
*code_alignment = local_code_alignment;
|
||||
*data_size = local_data_size;
|
||||
*data_alignment = local_data_alignment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_mutex.h"
|
||||
#include "tx_queue.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_external_memory_enable Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function adds an entry in the MPU table for a shared */
|
||||
/* memory space. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module instance pointer */
|
||||
/* start_address Start address of memory */
|
||||
/* length Length of external memory */
|
||||
/* attributes Memory attributes (r/w) */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_mutex_get Get protection mutex */
|
||||
/* _tx_mutex_put Release protection mutex */
|
||||
/* _txm_power_of_two_block_size Round length to power of two */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_external_memory_enable(TXM_MODULE_INSTANCE *module_instance,
|
||||
VOID *start_address,
|
||||
ULONG length,
|
||||
UINT attributes)
|
||||
{
|
||||
|
||||
ULONG block_size;
|
||||
ULONG region_size;
|
||||
ULONG srd_bits;
|
||||
ULONG size_register;
|
||||
ULONG address;
|
||||
ULONG shared_index;
|
||||
ULONG attributes_check = 0;
|
||||
|
||||
/* Determine if the module manager has been initialized. */
|
||||
if (_txm_module_manager_ready != TX_TRUE)
|
||||
{
|
||||
/* Module manager has not been initialized. */
|
||||
return(TX_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
/* Determine if the module is valid. */
|
||||
if (module_instance == TX_NULL)
|
||||
{
|
||||
/* Invalid module pointer. */
|
||||
return(TX_PTR_ERROR);
|
||||
}
|
||||
|
||||
/* Get module manager protection mutex. */
|
||||
_tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
|
||||
|
||||
/* Determine if the module instance is valid. */
|
||||
if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Invalid module pointer. */
|
||||
return(TX_PTR_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if the module instance is in the loaded state. */
|
||||
if (module_instance -> txm_module_instance_state != TXM_MODULE_LOADED)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return error if the module is not ready. */
|
||||
return(TX_START_ERROR);
|
||||
}
|
||||
|
||||
/* Determine if there are shared memory entries available. */
|
||||
if(module_instance -> txm_module_instance_shared_memory_count >= TXM_MODULE_MPU_SHARED_ENTRIES)
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* No more entries available. */
|
||||
return(TX_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Start address and length must adhere to Cortex-R MPU.
|
||||
The address must align with the block size. */
|
||||
|
||||
block_size = _txm_power_of_two_block_size(length);
|
||||
address = (ULONG) start_address;
|
||||
if(address != (address & ~(block_size - 1)))
|
||||
{
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return alignment error. */
|
||||
return(TXM_MODULE_ALIGNMENT_ERROR);
|
||||
}
|
||||
|
||||
/* At this point, we have a valid address and block size.
|
||||
Set up MPU registers. */
|
||||
|
||||
/* Generate index into shared memory entries. */
|
||||
shared_index = TXM_MODULE_MPU_SHARED_INDEX + module_instance -> txm_module_instance_shared_memory_count;
|
||||
|
||||
/* Save address register. */
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_address = address;
|
||||
|
||||
/* Calculate the region size. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
/* Calculate the subregion bits. */
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, length);
|
||||
|
||||
/* Save size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_size = size_register;
|
||||
|
||||
/* Check for optional attributes. */
|
||||
if(attributes & TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE)
|
||||
{
|
||||
attributes_check = TXM_MODULE_MANAGER_ATTRIBUTE_WRITE_MPU_BIT;
|
||||
}
|
||||
|
||||
/* Save attributes register. */
|
||||
module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_attributes = attributes_check | TXM_MODULE_MPU_SHARED_ACCESS_CONTROL;
|
||||
|
||||
/* Keep track of shared memory address and length in module instance. */
|
||||
module_instance -> txm_module_instance_shared_memory_address[module_instance -> txm_module_instance_shared_memory_count] = address;
|
||||
module_instance -> txm_module_instance_shared_memory_length[module_instance -> txm_module_instance_shared_memory_count] = length;
|
||||
|
||||
/* Increment counter. */
|
||||
module_instance -> txm_module_instance_shared_memory_count++;
|
||||
|
||||
/* Release the protection mutex. */
|
||||
_tx_mutex_put(&_txm_module_manager_mutex);
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
@@ -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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define the user's fault notification callback function pointer. This is
|
||||
setup via the txm_module_manager_memory_fault_notify API. */
|
||||
|
||||
VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
|
||||
|
||||
|
||||
/* Define a macro that can be used to allocate global variables useful to
|
||||
store information about the last fault. This macro is defined in
|
||||
txm_module_port.h and is usually populated in the assembly language
|
||||
fault handling prior to the code calling _txm_module_manager_memory_fault_handler. */
|
||||
|
||||
TXM_MODULE_MANAGER_FAULT_INFO
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_memory_fault_handler Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function handles a fault associated with a memory protected */
|
||||
/* module. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_terminate Terminate thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Fault handler */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_memory_fault_handler(VOID)
|
||||
{
|
||||
|
||||
TXM_MODULE_INSTANCE *module_instance_ptr;
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
|
||||
/* Pickup the current thread. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Initialize the module instance pointer to NULL. */
|
||||
module_instance_ptr = TX_NULL;
|
||||
|
||||
/* Is there a thread? */
|
||||
if (thread_ptr)
|
||||
{
|
||||
/* Pickup the module instance. */
|
||||
module_instance_ptr = thread_ptr -> tx_thread_module_instance_ptr;
|
||||
|
||||
/* Terminate the current thread. */
|
||||
_tx_thread_terminate(_tx_thread_current_ptr);
|
||||
}
|
||||
|
||||
/* Determine if there is a user memory fault notification callback. */
|
||||
if (_txm_module_manager_fault_notify)
|
||||
{
|
||||
/* Yes, call the user's notification memory fault callback. */
|
||||
(_txm_module_manager_fault_notify)(thread_ptr, module_instance_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
|
||||
/* Define the external user's fault notification callback function pointer. This is
|
||||
setup via the txm_module_manager_memory_fault_notify API. */
|
||||
|
||||
extern VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *);
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_memory_fault_notify Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function registers an application callback when/if a memory */
|
||||
/* fault occurs. The supplied thread is automatically terminated, but */
|
||||
/* any other threads in the same module may still execute. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* notify_function Memory fault notification */
|
||||
/* function, NULL disables. */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
{
|
||||
/* Setup notification function. */
|
||||
_txm_module_manager_fault_notify = notify_function;
|
||||
|
||||
/* Return success. */
|
||||
return(TX_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_region_size_get Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function converts the region size in bytes to the block size */
|
||||
/* for the Cortex-R4 MPU specification. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* block_size Size of the block in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* MPU size specification */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_module_manager_region_size_get(ULONG block_size)
|
||||
{
|
||||
|
||||
ULONG return_value;
|
||||
|
||||
/* Process relative to the input block size. */
|
||||
if (block_size == 32)
|
||||
{
|
||||
return_value = 0x04;
|
||||
}
|
||||
else if (block_size == 64)
|
||||
{
|
||||
return_value = 0x05;
|
||||
}
|
||||
else if (block_size == 128)
|
||||
{
|
||||
return_value = 0x06;
|
||||
}
|
||||
else if (block_size == 256)
|
||||
{
|
||||
return_value = 0x07;
|
||||
}
|
||||
else if (block_size == 512)
|
||||
{
|
||||
return_value = 0x08;
|
||||
}
|
||||
else if (block_size == 1024)
|
||||
{
|
||||
return_value = 0x09;
|
||||
}
|
||||
else if (block_size == 2048)
|
||||
{
|
||||
return_value = 0x0A;
|
||||
}
|
||||
else if (block_size == 4096)
|
||||
{
|
||||
return_value = 0x0B;
|
||||
}
|
||||
else if (block_size == 8192)
|
||||
{
|
||||
return_value = 0x0C;
|
||||
}
|
||||
else if (block_size == 16384)
|
||||
{
|
||||
return_value = 0x0D;
|
||||
}
|
||||
else if (block_size == 32768)
|
||||
{
|
||||
return_value = 0x0E;
|
||||
}
|
||||
else if (block_size == 65536)
|
||||
{
|
||||
return_value = 0x0F;
|
||||
}
|
||||
else if (block_size == 131072)
|
||||
{
|
||||
return_value = 0x10;
|
||||
}
|
||||
else if (block_size == 262144)
|
||||
{
|
||||
return_value = 0x11;
|
||||
}
|
||||
else if (block_size == 524288)
|
||||
{
|
||||
return_value = 0x12;
|
||||
}
|
||||
else if (block_size == 1048576)
|
||||
{
|
||||
return_value = 0x13;
|
||||
}
|
||||
else if (block_size == 2097152)
|
||||
{
|
||||
return_value = 0x14;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Max 4MB MPU pages for modules. */
|
||||
return_value = 0x15;
|
||||
}
|
||||
|
||||
return(return_value);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_calculate_srd_bits Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function calculates the SRD bits that need to be set to */
|
||||
/* protect "length" bytes in a block. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* block_size Size of the block in bytes */
|
||||
/* length Actual length in bytes */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* SRD bits to be OR'ed with region attribute register. */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ULONG _txm_module_manager_calculate_srd_bits(ULONG block_size, ULONG length)
|
||||
{
|
||||
|
||||
ULONG srd_bits = 0;
|
||||
UINT srd_bit_index;
|
||||
|
||||
/* length is smaller than block_size, set SRD bits if block_size is 256 or more. */
|
||||
if((block_size >= 256) && (length < block_size))
|
||||
{
|
||||
/* Divide block_size by 8 by shifting right 3. Result is size of subregion. */
|
||||
block_size = block_size >> 3;
|
||||
|
||||
/* Set SRD index into attribute register. */
|
||||
srd_bit_index = 8;
|
||||
|
||||
/* If subregion overlaps length, move to the next subregion. */
|
||||
while(length > block_size)
|
||||
{
|
||||
length = length - block_size;
|
||||
srd_bit_index++;
|
||||
}
|
||||
|
||||
/* Check for a portion of code remaining. */
|
||||
if(length)
|
||||
{
|
||||
srd_bit_index++;
|
||||
}
|
||||
|
||||
/* Set unused subregion bits. */
|
||||
while(srd_bit_index < 16)
|
||||
{
|
||||
srd_bits = srd_bits | (0x1 << srd_bit_index);
|
||||
srd_bit_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return(srd_bits);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_mm_register_setup Cortex-R4/MPU/IAR */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function sets up the MPU register definitions based on the */
|
||||
/* module's memory characteristics. */
|
||||
/* MPU layout for the Cortex-R4: */
|
||||
/* Entry Description */
|
||||
/* 0 Kernel mode entry */
|
||||
/* 1 Module code region */
|
||||
/* 2 Module code region */
|
||||
/* 3 Module code region */
|
||||
/* 4 Module code region */
|
||||
/* 5 Module data region */
|
||||
/* 6 Module data region */
|
||||
/* 7 Module data region */
|
||||
/* 8 Module data region */
|
||||
/* 9 Module shared memory region */
|
||||
/* 10 Module shared memory region */
|
||||
/* 11 Module shared memory region */
|
||||
/* */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Pointer to module instance */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* MPU specifications for module in module_instance */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _txm_module_manager_region_size_get */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_create */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance)
|
||||
{
|
||||
|
||||
ULONG code_address;
|
||||
ULONG code_size;
|
||||
ULONG data_address;
|
||||
ULONG data_size;
|
||||
ULONG start_stop_stack_size;
|
||||
ULONG callback_stack_size;
|
||||
ULONG block_size;
|
||||
ULONG base_address_register;
|
||||
ULONG size_register;
|
||||
ULONG region_size;
|
||||
ULONG srd_bits = 0;
|
||||
UINT mpu_table_index;
|
||||
UINT i;
|
||||
|
||||
|
||||
/* Setup the first region for kernel mode entry. */
|
||||
|
||||
/* Set address register to user mode entry function address, which is guaranteed to be at least 32-byte aligned. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_address = (ULONG) _txm_module_manager_user_mode_entry;
|
||||
|
||||
/* Set the size (32 bytes) and enable bit. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_size = (_txm_module_manager_region_size_get(32) << 1) | TXM_ENABLE_REGION;
|
||||
|
||||
/* Set attributes. */
|
||||
module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_attributes = TXM_MODULE_MPU_CODE_ACCESS_CONTROL;
|
||||
|
||||
/* End of kernel mode entry setup. */
|
||||
|
||||
/* Setup code protection. */
|
||||
|
||||
/* Initialize the MPU table index. */
|
||||
mpu_table_index = 1;
|
||||
|
||||
/* Pickup code starting address and actual size. */
|
||||
code_address = (ULONG) module_instance -> txm_module_instance_code_start;
|
||||
code_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_code_size;
|
||||
|
||||
/* Determine code block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU code entries available. The following is how the code size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to code size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
|
||||
/* Now loop through to setup MPU protection for the code area. */
|
||||
for (i = 0; i < TXM_MODULE_MPU_CODE_ENTRIES; i++)
|
||||
{
|
||||
/* First two MPU blocks are 1/4 of the largest power of two
|
||||
that is greater than or equal to code size. */
|
||||
if (i < 2)
|
||||
{
|
||||
block_size = _txm_power_of_two_block_size(code_size) >> 2;
|
||||
}
|
||||
|
||||
/* Third MPU block is the largest power of 2 that fits in the remaining space. */
|
||||
else if (i == 2)
|
||||
{
|
||||
/* Subtract (block_size*2) from code_size to calculate remaining space. */
|
||||
code_size = code_size - (block_size << 1);
|
||||
block_size = _txm_power_of_two_block_size(code_size) >> 1;
|
||||
}
|
||||
|
||||
/* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
else
|
||||
{
|
||||
/* Calculate remaining space. */
|
||||
code_size = code_size - block_size;
|
||||
block_size = _txm_power_of_two_block_size(code_size);
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, code_size);
|
||||
}
|
||||
|
||||
/* Build the base address register. */
|
||||
base_address_register = (code_address & ~(block_size - 1));
|
||||
|
||||
/* Calculate the region size information. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
|
||||
/* Build the size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
|
||||
/* Setup the MPU address, size, and attribute registers. */
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = base_address_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_size = size_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attributes = TXM_MODULE_MPU_CODE_ACCESS_CONTROL;
|
||||
|
||||
/* Adjust the code address. */
|
||||
code_address = code_address + block_size;
|
||||
|
||||
/* Increment MPU table index. */
|
||||
mpu_table_index++;
|
||||
}
|
||||
/* End of code protection. */
|
||||
|
||||
/* Setup data protection. */
|
||||
|
||||
/* Reset SRD bitfield. */
|
||||
srd_bits = 0;
|
||||
|
||||
/* Pickup data starting address and actual size. */
|
||||
data_address = (ULONG) module_instance -> txm_module_instance_data_start;
|
||||
|
||||
/* Adjust the size of the module elements to be aligned to the default alignment. We do this
|
||||
so that when we partition the allocated memory, we can simply place these regions right beside
|
||||
each other without having to align their pointers. Note this only works when they all have
|
||||
the same alignment. */
|
||||
|
||||
data_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_data_size;
|
||||
start_stop_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_start_stop_stack_size;
|
||||
callback_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_callback_stack_size;
|
||||
|
||||
data_size = ((data_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
start_stop_stack_size = ((start_stop_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
callback_stack_size = ((callback_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT;
|
||||
|
||||
/* Update the data size to include thread stacks. */
|
||||
data_size = data_size + start_stop_stack_size + callback_stack_size;
|
||||
|
||||
/* Determine data block sizes. Minimize the alignment requirement.
|
||||
There are 4 MPU data entries available. The following is how the data size
|
||||
will be distributed:
|
||||
1. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
2. 1/4 of the largest power of two that is greater than or equal to data size.
|
||||
3. Largest power of 2 that fits in the remaining space.
|
||||
4. Smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
|
||||
/* Now loop through to setup MPU protection for the data area. */
|
||||
for (i = 0; i < TXM_MODULE_MPU_DATA_ENTRIES; i++)
|
||||
{
|
||||
/* First two MPU blocks are 1/4 of the largest power of two
|
||||
that is greater than or equal to data size. */
|
||||
if (i < 2)
|
||||
{
|
||||
block_size = _txm_power_of_two_block_size(data_size) >> 2;
|
||||
}
|
||||
|
||||
/* Third MPU block is the largest power of 2 that fits in the remaining space. */
|
||||
else if (i == 2)
|
||||
{
|
||||
/* Subtract (block_size*2) from data_size to calculate remaining space. */
|
||||
data_size = data_size - (block_size << 1);
|
||||
block_size = _txm_power_of_two_block_size(data_size) >> 1;
|
||||
}
|
||||
|
||||
/* Last MPU block is the smallest power of 2 that exceeds the remaining space, minimum 32. */
|
||||
else
|
||||
{
|
||||
/* Calculate remaining space. */
|
||||
data_size = data_size - block_size;
|
||||
block_size = _txm_power_of_two_block_size(data_size);
|
||||
srd_bits = _txm_module_manager_calculate_srd_bits(block_size, data_size);
|
||||
}
|
||||
|
||||
/* Build the base address register. */
|
||||
base_address_register = (data_address & ~(block_size - 1));
|
||||
|
||||
/* Calculate the region size information. */
|
||||
region_size = (_txm_module_manager_region_size_get(block_size) << 1);
|
||||
|
||||
/* Build the size register. */
|
||||
size_register = srd_bits | region_size | TXM_ENABLE_REGION;
|
||||
|
||||
/* Setup the MPU address, size, and attribute registers. */
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_address = base_address_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_size = size_register;
|
||||
module_instance -> txm_module_instance_mpu_registers[mpu_table_index].txm_module_mpu_region_attributes = TXM_MODULE_MPU_DATA_ACCESS_CONTROL;
|
||||
|
||||
/* Adjust the data address. */
|
||||
data_address = data_address + block_size;
|
||||
|
||||
/* Increment MPU table index. */
|
||||
mpu_table_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_inside_data_check Cortex-R4/MPU/IAR */
|
||||
/* 6.1.6 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function checks if the specified object is inside shared */
|
||||
/* memory. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Pointer to module instance */
|
||||
/* obj_ptr Pointer to the object */
|
||||
/* obj_size Size of the object */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Whether the object is inside the shared memory region. */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* N/A */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Module dispatch check functions */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
/* 04-02-2021 Scott Larson Modified comments, added */
|
||||
/* check for overflow, *
|
||||
/* resulting in version 6.1.6 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size)
|
||||
{
|
||||
|
||||
UINT shared_memory_index;
|
||||
UINT num_shared_memory_mpu_entries;
|
||||
ALIGN_TYPE shared_memory_address_start;
|
||||
ALIGN_TYPE shared_memory_address_end;
|
||||
|
||||
/* Check for overflow. */
|
||||
if ((obj_ptr) > ((obj_ptr) + (obj_size)))
|
||||
{
|
||||
return(TX_FALSE);
|
||||
}
|
||||
|
||||
/* Check if the object is inside the module data. */
|
||||
if ((obj_ptr >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) &&
|
||||
((obj_ptr + obj_size) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1)))
|
||||
{
|
||||
return(TX_TRUE);
|
||||
}
|
||||
|
||||
/* Check if the object is inside the shared memory. */
|
||||
num_shared_memory_mpu_entries = module_instance -> txm_module_instance_shared_memory_count;
|
||||
for (shared_memory_index = 0; shared_memory_index < num_shared_memory_mpu_entries; shared_memory_index++)
|
||||
{
|
||||
|
||||
shared_memory_address_start = (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address[shared_memory_index];
|
||||
shared_memory_address_end = shared_memory_address_start + module_instance -> txm_module_instance_shared_memory_length[shared_memory_index];
|
||||
|
||||
if ((obj_ptr >= (ALIGN_TYPE) shared_memory_address_start) &&
|
||||
((obj_ptr + obj_size) <= (ALIGN_TYPE) shared_memory_address_end))
|
||||
{
|
||||
return(TX_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return(TX_FALSE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* 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 */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
THUMB_MASK DEFINE 0x20 ; THUMB bit
|
||||
USR_MODE DEFINE 0x10 ; USR mode
|
||||
SYS_MODE DEFINE 0x1F ; SYS mode
|
||||
CPSR_MASK DEFINE 0xBF ; Mask initial CPSR, IRQ ints enabled
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _txm_module_manager_thread_stack_build Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function builds a stack frame on the supplied thread's stack. */
|
||||
;/* The stack frame results in a fake interrupt return to the supplied */
|
||||
;/* function pointer. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* thread_ptr Pointer to thread control blk */
|
||||
;/* function_ptr Pointer to return function */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* _tx_thread_create Create thread service */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
;{
|
||||
RSEG .text:CODE:NOROOT(2)
|
||||
PUBLIC _txm_module_manager_thread_stack_build
|
||||
ARM
|
||||
_txm_module_manager_thread_stack_build
|
||||
;
|
||||
;
|
||||
; /* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
; on the Cortex-R4 should look like the following after it is built:
|
||||
;
|
||||
; Stack Top: 1 Interrupt stack frame type
|
||||
; CPSR Initial value for CPSR
|
||||
; r0 Initial value for r0
|
||||
; r1 Initial value for r1
|
||||
; r2 Initial value for r2
|
||||
; r3 Initial value for r3
|
||||
; r4 Initial value for r4
|
||||
; r5 Initial value for r5
|
||||
; r6 Initial value for r6
|
||||
; r7 Initial value for r7
|
||||
; r8 Initial value for r8
|
||||
; r9 Initial value for r9
|
||||
; r10 Initial value for r10
|
||||
; r11 Initial value for r11
|
||||
; r12 Initial value for r12
|
||||
; lr Initial value for lr (r14)
|
||||
; pc Initial value for pc (r15)
|
||||
; 0 For stack backtracing
|
||||
;
|
||||
; Stack Bottom: (higher memory address) */
|
||||
;
|
||||
LDR r2, [r0, #16] ; Pickup end of stack area
|
||||
BIC r2, r2, #7 ; Ensure 8-byte alignment
|
||||
SUB r2, r2, #76 ; Allocate space for the stack frame
|
||||
;
|
||||
; /* Actually build the stack frame. */
|
||||
;
|
||||
MOV r3, #1 ; Build interrupt stack type
|
||||
STR r3, [r2, #0] ; Store stack type
|
||||
STR r0, [r2, #8] ; Store initial r0 (thread pointer)
|
||||
LDR r3, [r0, #8] ; Pickup thread info pointer (it's in the stack pointer location right now)
|
||||
STR r3, [r2, #12] ; Store initial r1
|
||||
LDR r3, [r3, #8] ; Pickup data base register
|
||||
STR r3, [r2, #44] ; Store initial r9
|
||||
MOV r3, #0 ; Build initial register value
|
||||
STR r3, [r2, #16] ; Store initial r2
|
||||
STR r3, [r2, #20] ; Store initial r3
|
||||
STR r3, [r2, #24] ; Store initial r4
|
||||
STR r3, [r2, #28] ; Store initial r5
|
||||
STR r3, [r2, #32] ; Store initial r6
|
||||
STR r3, [r2, #36] ; Store initial r7
|
||||
STR r3, [r2, #40] ; Store initial r8
|
||||
LDR r3, [r0, #12] ; Pickup stack starting address
|
||||
STR r3, [r2, #48] ; Store initial r10 (sl)
|
||||
MOV r3, #0 ; Build initial register value
|
||||
STR r3, [r2, #52] ; Store initial r11
|
||||
STR r3, [r2, #56] ; Store initial r12
|
||||
STR r3, [r2, #60] ; Store initial lr
|
||||
STR r1, [r2, #64] ; Store initial pc
|
||||
STR r3, [r2, #68] ; 0 for back-trace
|
||||
MRS r3, CPSR ; Pickup CPSR
|
||||
BIC r3, r3, #CPSR_MASK ; Mask mode bits of CPSR
|
||||
TST r1, #1 ; Test if THUMB bit set in initial PC
|
||||
ORRNE r3, r3, #THUMB_MASK ; Set T bit if set
|
||||
LDR r1, [r0, #156] ; Load tx_thread_module_user_mode
|
||||
TST r1, #1 ; Test if the user mode flag is set
|
||||
ORREQ r3, r3, #SYS_MODE ; Flag not set: Build CPSR, SYS mode, IRQ enabled
|
||||
ORRNE r3, r3, #USR_MODE ; Flag set: Build CPSR, USR mode, IRQ enabled
|
||||
STR r3, [r2, #4] ; Store initial CPSR
|
||||
;
|
||||
; /* Setup stack pointer. */
|
||||
; thread_ptr -> tx_thread_stack_ptr = r2;
|
||||
;
|
||||
STR r2, [r0, #8] ; Save stack pointer in thread's control block
|
||||
BX lr ; Return to caller
|
||||
;}
|
||||
END
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
;/* */
|
||||
;/* This software is licensed under the Microsoft Software License */
|
||||
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
;/* and in the root directory of this software. */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
;
|
||||
;
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;/** */
|
||||
;/** ThreadX Component */
|
||||
;/** */
|
||||
;/** Thread */
|
||||
;/** */
|
||||
;/**************************************************************************/
|
||||
;/**************************************************************************/
|
||||
;
|
||||
EXTERN _tx_thread_current_ptr
|
||||
EXTERN _txm_module_manager_kernel_dispatch
|
||||
|
||||
|
||||
RSEG .text:CODE:NOROOT(5)
|
||||
ARM
|
||||
;/**************************************************************************/
|
||||
;/* */
|
||||
;/* FUNCTION RELEASE */
|
||||
;/* */
|
||||
;/* _txm_module_manager_user_mode_entry Cortex-R4/MPU/IAR */
|
||||
;/* 6.1 */
|
||||
;/* AUTHOR */
|
||||
;/* */
|
||||
;/* Scott Larson, Microsoft Corporation */
|
||||
;/* */
|
||||
;/* DESCRIPTION */
|
||||
;/* */
|
||||
;/* This function allows modules to enter kernel mode. */
|
||||
;/* */
|
||||
;/* INPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* OUTPUT */
|
||||
;/* */
|
||||
;/* None */
|
||||
;/* */
|
||||
;/* CALLS */
|
||||
;/* */
|
||||
;/* SVC 1 Enter kernel mode */
|
||||
;/* SVC 2 Exit kernel mode */
|
||||
;/* */
|
||||
;/* CALLED BY */
|
||||
;/* */
|
||||
;/* Modules in user mode */
|
||||
;/* */
|
||||
;/* RELEASE HISTORY */
|
||||
;/* */
|
||||
;/* DATE NAME DESCRIPTION */
|
||||
;/* */
|
||||
;/* 09-30-2020 Scott Larson Initial Version 6.1 */
|
||||
;/* */
|
||||
;/**************************************************************************/
|
||||
PUBLIC _txm_module_manager_user_mode_entry
|
||||
_txm_module_manager_user_mode_entry:
|
||||
|
||||
EXPORT _txm_system_mode_enter
|
||||
_txm_system_mode_enter
|
||||
SVC 1 ; Get out of user mode
|
||||
_txm_module_priv
|
||||
; At this point, we are in system mode.
|
||||
; Save LR (and r3 for 8 byte aligned stack) and call the kernel dispatch function.
|
||||
PUSH {r3, lr}
|
||||
BL _txm_module_manager_kernel_dispatch
|
||||
POP {r3, lr}
|
||||
|
||||
EXPORT _txm_system_mode_exit
|
||||
_txm_system_mode_exit
|
||||
; Trap to restore user mode while inside of ThreadX
|
||||
SVC 2
|
||||
|
||||
BX lr ; Return to the caller
|
||||
NOP
|
||||
NOP
|
||||
_txm_module_manager_user_mode_end
|
||||
|
||||
END
|
||||
Reference in New Issue
Block a user