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