summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKshitij Sisodia <kshitij.sisodia@arm.com>2024-04-08 09:58:46 +0100
committerKshitij Sisodia <kshitij.sisodia@arm.com>2024-05-03 14:52:28 +0100
commit4cef9acc2624a31111b47c25b8b1a2f37f7e0cb9 (patch)
tree6a43d17ae1ded33b4115dbe2cd70fcad42a027a3
parent6bc730c0aab22aa0ac147283a1b19eaf11a80d1a (diff)
downloadml-embedded-evaluation-kit-main.tar.gz
MLECO-4825: Adding Arm Corstone-315 supportHEADmain
This patch adds initial support for MPS4 based Arm Corstone-315 FVPs. The applications will execute on the FVP but with INITSVTOR set to `0x12000000` explicitly. The default value is the 64kiB code region at `0x11000000`. The linker scripts will be changed for the initial boot logic and vector table to be moved to the code region. This patch adds `source/hal/source/platform/mps4` directory. There is considerable overlap with MPS3 platform and this is expected to be the case until the support for MPS4 matures. Refactoring to pull in common bits from these targets will follow. Same goes for the CMake build support added under `scripts/cmake/platforms/mps4`. Change-Id: I981be9e1ec57cfedcf7d340b4f19e5eb40b5cbd3 Signed-off-by: Kshitij Sisodia <kshitij.sisodia@arm.com> Tested-by: mlecosys <mlecosys@arm.com> Reviewed-by: Conor Kennedy <conor.kennedy@arm.com> Reviewed-by: Alex Tawse <alex.tawse@arm.com> Signed-off-by: Kshitij Sisodia <kshitij.sisodia@arm.com>
-rw-r--r--CMakeLists.txt4
-rw-r--r--CMakePresets.json26
-rw-r--r--docs/documentation.md9
-rw-r--r--docs/sections/building.md11
-rw-r--r--docs/sections/deployment.md69
-rw-r--r--scripts/cmake/platforms/mps4/build_configuration.cmake111
-rw-r--r--scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.ld218
-rw-r--r--scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.sct143
-rw-r--r--scripts/cmake/platforms/platforms-preset.json19
-rw-r--r--scripts/mps4/sse-315/images.txt14
-rw-r--r--source/application/main/Main.cc5
-rw-r--r--source/hal/source/platform/mps4/CMakeLists.txt150
-rw-r--r--source/hal/source/platform/mps4/include/platform_drivers.h47
-rw-r--r--source/hal/source/platform/mps4/include/sse-315/mem_regions.h124
-rw-r--r--source/hal/source/platform/mps4/include/sse-315/peripheral_irqs.h121
-rw-r--r--source/hal/source/platform/mps4/include/sse-315/peripheral_memmap.h196
-rw-r--r--source/hal/source/platform/mps4/include/timer_mps4.h64
-rw-r--r--source/hal/source/platform/mps4/readme.md3
-rw-r--r--source/hal/source/platform/mps4/source/platform_drivers.c180
-rw-r--r--source/hal/source/platform/mps4/source/smm_mps4.h152
-rw-r--r--source/hal/source/platform/mps4/source/timer_mps4.c230
21 files changed, 1856 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fbf3b72..c458eb9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
#----------------------------------------------------------------------------
-# SPDX-FileCopyrightText: Copyright 2021-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -84,7 +84,7 @@ if(POLICY CMP0123)
endif()
project(arm_ml_embedded_evaluation_kit
- VERSION 23.11.0
+ VERSION 24.02.0
DESCRIPTION "ARM ML Embedded Evaluation Kit"
LANGUAGES C CXX ASM)
diff --git a/CMakePresets.json b/CMakePresets.json
index 3500329..0385b04 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -33,7 +33,7 @@
{
"name": "mps3-300-gcc",
"displayName": "mps3-300-gcc",
- "description": "Target mps3 board, SSE-300 subsystem with bare-metal gcc toolchain.",
+ "description": "Target MPS3 board, SSE-300 subsystem with bare-metal gcc toolchain.",
"inherits": [
"mps3-300-platform",
"gcc-toolchain"
@@ -42,7 +42,7 @@
{
"name": "mps3-300-clang",
"displayName": "mps3-300-armclang",
- "description": "Target mps3 board, SSE-300 subsystem with bare-metal armclang toolchain.",
+ "description": "Target MPS3 board, SSE-300 subsystem with bare-metal armclang toolchain.",
"inherits": [
"mps3-300-platform",
"armclang-toolchain"
@@ -51,7 +51,7 @@
{
"name": "mps3-310-gcc",
"displayName": "mps3-310-gcc",
- "description": "Target mps3 board, SSE-310 subsystem with bare-metal gcc toolchain.",
+ "description": "Target MPS3 board, SSE-310 subsystem with bare-metal gcc toolchain.",
"inherits": [
"mps3-310-platform",
"gcc-toolchain"
@@ -60,13 +60,31 @@
{
"name": "mps3-310-clang",
"displayName": "mps3-310-armclang",
- "description": "Target mps3 board, SSE-310 subsystem with bare-metal armclang toolchain.",
+ "description": "Target MPS3 board, SSE-310 subsystem with bare-metal armclang toolchain.",
"inherits": [
"mps3-310-platform",
"armclang-toolchain"
]
},
{
+ "name": "mps4-315-gcc",
+ "displayName": "mps3-315-gcc",
+ "description": "Target MPS4 board, SSE-315 subsystem with bare-metal gcc toolchain.",
+ "inherits": [
+ "mps4-315-platform",
+ "gcc-toolchain"
+ ]
+ },
+ {
+ "name": "mps4-315-clang",
+ "displayName": "mps4-315-armclang",
+ "description": "Target MPS4 board, SSE-315 subsystem with bare-metal armclang toolchain.",
+ "inherits": [
+ "mps4-315-platform",
+ "armclang-toolchain"
+ ]
+ },
+ {
"name": "native",
"displayName": "native",
"description": "Target native system.",
diff --git a/docs/documentation.md b/docs/documentation.md
index 5f24942..0476418 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -42,12 +42,15 @@ Before starting the setup process, please make sure that you have:
- An Arm® MPS3 FPGA prototyping board and components for FPGA evaluation or a `Fixed Virtual Platform` binary:
- An MPS3 board loaded with Arm® Corstone™-300 (`AN552`) or Corstone™-310 reference package (`AN555`). See
- <https://developer.arm.com/downloads/-/download-fpga-images>. You
+ [Download FPGA Images](https://developer.arm.com/downloads/-/download-fpga-images). You
must have a USB connection between your machine and the MPS3 board - for UART menu and for deploying the
application.
- Both `Arm® Corstone™-300` and `Arm® Corstone™-310` based FVPs for MPS3 are available from:
- <https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps>
- and as Arm® Virtual Hardware: <https://www.arm.com/products/development-tools/simulation/virtual-hardware>
+ [Arm® Ecosystem FVPs](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps)
+ and as [Arm® Virtual Hardware](https://www.arm.com/products/development-tools/simulation/virtual-hardware)
+- An Arm® MPS4 `Fixed Virtual Platform` binary to try the latest `Arm® Corstone™-315` reference platform. This can also
+ be downloaded from [Arm® Ecosystem FVPs](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps)
+ page.
> **Note:**: There are two Arm® Corstone™-300 implementations available for the MPS3 FPGA board - application
> notes `AN547` and `AN552`. We are aligned with the latest application note `AN552`. However, the application built
diff --git a/docs/sections/building.md b/docs/sections/building.md
index d20e570..7854c6a 100644
--- a/docs/sections/building.md
+++ b/docs/sections/building.md
@@ -175,13 +175,16 @@ The build parameters are:
- `TARGET_PLATFORM`: The target platform to execute the application on:
- `mps3` (default)
+ - `mps4`
- `native`
- `simple_platform`
-- `TARGET_SUBSYSTEM`: The target platform subsystem. Specifies the design implementation for the deployment target. For
- both, the MPS3 FVP and the MPS3 FPGA, this must be left to the default value of SSE-300:
- - `sse-300` (default - [Arm® Corstone™-300](https://developer.arm.com/ip-products/subsystem/corstone/corstone-300))
- - `sse-310` (The FVP is available via Arm Virtual Hardware (AVH) hosted on AWS)
+- `TARGET_SUBSYSTEM`: The target platform subsystem. Specifies the design implementation for the deployment target.
+ For `mps3` target these sub-systems are available:
+ - `sse-300`: this is the default, see [Arm® Corstone™-300](https://developer.arm.com/Processors/Corstone-300)
+ - `sse-310`: See [Arm® Corstone™-310](https://developer.arm.com/Processors/Corstone-310)
+ For `mps4` target:
+ - `sse-315`: See [Arm® Corstone™-315](https://developer.arm.com/Processors/Corstone-315)
- `CMAKE_TOOLCHAIN_FILE`: This built-in CMake parameter can be used to override the default toolchain file used for the
build. All the valid toolchain files are located in the scripts directory. For example, see:
diff --git a/docs/sections/deployment.md b/docs/sections/deployment.md
index 15a58c3..d51d912 100644
--- a/docs/sections/deployment.md
+++ b/docs/sections/deployment.md
@@ -2,10 +2,10 @@
- [Deployment](./deployment.md#deployment)
- [Fixed Virtual Platform](./deployment.md#fixed-virtual-platform)
- - [Setting up the MPS3 Arm Corstone-300 FVP](./deployment.md#setting-up-the-mps3-arm-corstone_300-fvp)
- - [Deploying on an FVP emulating MPS3](./deployment.md#deploying-on-an-fvp-emulating-mps3)
+ - [Installing an FVP](./deployment.md#installing-an-fvp)
+ - [Deploying on an FVP](./deployment.md#deploying-on-an-fvp)
- [Running the FVP without the UI](./deployment.md#running-the-fvp-without-the-ui)
- - [MPS3 board](./deployment.md#mps3-board)
+ - [MPS3 FPGA board](./deployment.md#mps3-fpga-board)
- [MPS3 board top-view](./deployment.md#mps3-board-top_view)
- [Deployment on MPS3 board](./deployment.md#deployment-on-mps3-board)
@@ -27,22 +27,23 @@ Please ensure that you download the correct archive from the list under Arm® Co
- Emulates MPS3 board and *not* for MPS2 FPGA board,
- Contains support for Arm® Ethos™-U55 and Ethos™-U65 processors.
-### Setting up the MPS3 Arm Corstone-300 FVP
+### Installing an FVP
-To install the FVP:
+To install an FVP:
-- Unpack the archive.
+- Unpack the archive downloaded from [Arm® Ecosystem FVPs](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps).
-- Run the installation script in the extracted package:
-
- `./FVP_Corstone_SSE-300.sh`
+- Run the installation script in the extracted package. For example, `Arm® Corstone™-300` package will have
+ `FVP_Corstone_SSE-300.sh`.
- Follow the instructions to install the FVP to your required location.
-### Deploying on an FVP emulating MPS3
+> **Note**: The installation process is the same for other FVPs (Arm® Corstone™-310 and Corstone™-315) too.
+
+### Deploying on an FVP
This section assumes that the FVP has been installed (see
-[Setting up the MPS3 Arm Corstone-300 FVP](./deployment.md#setting-up-the-mps3-arm-corstone-300-fvp))
+[Installing an FVP](./deployment.md#installing-an-fvp))
to the home directory of the user: `~/FVP_Corstone_SSE-300`. The installation, typically, has the
executable under `~/FVP_Corstone_SSE-300/model/<OS>_<compiler-version>/` directory. For the example
below, we assume it is: `~/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4`.
@@ -51,7 +52,7 @@ For Arm Virtual Hardware, the installation paths are different (see Arm Virtual
[Useful Links](./arm_virtual_hardware.md#useful-links) section).
> **NOTE**: The commandline arguments for the FVP mentioned below are valid for FVPs (and AVH) for
-> both Arm® Corstone™-300 and Corstone™-310.
+> Arm® Corstone™-300, Corstone™-310 and Corstone™-315.
To run a use-case on the FVP, from the [Build directory](../sections/building.md#create-a-build-directory):
@@ -100,13 +101,21 @@ The FVP supports many command-line parameters, such as:
The number signifies the 8x8 MACs that are performed per cycle-count and that are available on
the hardware.
- - `cpu0.CFGITCMSZ`: The ITCM size for the *Cortex-M* CPU. The size of ITCM is *pow(2, CFGITCMSZ - 1)* KB
- - `cpu0.CFGDTCMSZ`: The DTCM size for the *Cortex-M* CPU. The size of DTCM is *pow(2, CFGDTCMSZ - 1)* KB
- - `mps3_board.telnetterminal0.start_telnet`: Starts the telnet session if nothing connected.
- - `mps3_board.uart0.out_file`: Sets the output file to hold the data written by the UART. Use `'-'` to send all output
- to `stdout` and is empty by default).
- - `mps3_board.uart0.shutdown_on_eot`: Shut down the simulation when an `EOT (ASCII 4)` char is transmitted.
- - `mps3_board.visualisation.disable-visualisation`: Enables, or disables, visualization and is disabled by default.
+ - For `MPS3` based FVPs:
+ - `cpu0.CFGITCMSZ`: The ITCM size for the *Cortex-M* CPU. The size of ITCM is *pow(2, CFGITCMSZ - 1)* KB
+ - `cpu0.CFGDTCMSZ`: The DTCM size for the *Cortex-M* CPU. The size of DTCM is *pow(2, CFGDTCMSZ - 1)* KB
+ - `mps3_board.telnetterminal0.start_telnet`: Starts the telnet session if nothing connected.
+ - `mps3_board.uart0.out_file`: Sets the output file to hold the data written by the UART. Use `'-'` to send all output
+ to `stdout` and is empty by default).
+ - `mps3_board.uart0.shutdown_on_eot`: Shut down the simulation when an `EOT (ASCII 4)` char is transmitted.
+ - `mps3_board.visualisation.disable-visualisation`: Enables, or disables, visualization and is disabled by default.
+ - For `MPS4` based FVPs, the equivalent parameters for the list above are:
+ - `mps4_board.subsystem.cpu0.CFGITCMSZ`
+ - `mps4_board.subsystem.cpu0.CFGDTCMSZ`
+ - `mps4_board.telnetterminal0.start_telnet`
+ - `mps4_board.uart0.out_file`
+ - `mps4_board.uart0.shutdown_on_eot`
+ - `mps4_board.visualisation.disable-visualisation` and `vis_hdlcd.disable_visualisation`.
To start the model in `128` mode for *Ethos-U55*:
@@ -136,8 +145,8 @@ The FVP supports many command-line parameters, such as:
### Running the FVP without the UI
-If there is a need to run the FVP without the UI (e.g running the FVP inside of a docker container),
-it can be done as follows:
+If there is a need to run the FVP without the UI (e.g. running the FVP inside a Docker container),
+it can be done as follows.
Add `-C mps3_board.visualisation.disable-visualisation=1` and `-C mps3_board.telnetterminal0.start_telnet=0`
to the command line arguments when starting the FVP. For example:
@@ -148,15 +157,29 @@ FVP_install_location/models/Linux64_GCC-6.4/FVP_Corstone_SSE-300_Ethos-U55 \
-C mps3_board.telnetterminal0.start_telnet=0 \
./bin/mps3-sse-300/ethos-u-<use_case>.axf
```
+For an `MPS4` FVP, the arguments are similar. For example:
+```commandline
+FVP_install_location/models/Linux64_GCC-9.3/FVP_Corstone_SSE-315 \
+ -C mps4_board.visualisation.disable-visualisation=1 \
+ -C vis_hdlcd.disable_visualisation=1 \
+ -C mps4_board.telnetterminal0.start_telnet=0 \
+ ./bin/mps4-sse-315/ethos-u-<use_case>.axf
+ ```
-Once the FVP reports waiting on telnet connections, connect to the first serverport from another terminal.
+Once the FVP reports waiting on telnet connections, connect to the first server port from another terminal.
Assuming the FVP has the telnet server running at the default port 5000, connect to it by:
```commandline
telnet localhost 5000
```
-## MPS3 board
+For applications that are configured with `USE_SINGLE_INPUT` CMake option, there is no interaction on telnet needed and
+the application output can be directed to standard output by using an FVP option:
+
+- `-C mps3_board.uart0.out_file='-'` for MPS3 based FVPs, OR
+- `-C mps4_board.uart0.out_file='-'` for MPS4 based FVPs.
+
+## MPS3 FPGA board
> **Note:** Before proceeding, make sure that you have the MPS3 board powered on, and a USB A to B cable connected
> between your machine and the MPS3. The connector on the MPS3 is marked as "Debug USB".
diff --git a/scripts/cmake/platforms/mps4/build_configuration.cmake b/scripts/cmake/platforms/mps4/build_configuration.cmake
new file mode 100644
index 0000000..3a3966d
--- /dev/null
+++ b/scripts/cmake/platforms/mps4/build_configuration.cmake
@@ -0,0 +1,111 @@
+#----------------------------------------------------------------------------
+# SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#----------------------------------------------------------------------------
+
+function(set_platform_global_defaults)
+ message(STATUS "Platform: Arm MPS4 FPGA Prototyping Board or FVP")
+
+ if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
+ if(TARGET_SUBSYSTEM STREQUAL sse-315)
+ set(CMAKE_SYSTEM_PROCESSOR cortex-m85 CACHE STRING "Cortex-M CPU to use")
+ else()
+ message(FATAL_ERROR "${TARGET_SUBSYSTEM} unsupported by ${TARGET_PLATFORM}")
+ endif()
+ endif()
+
+ if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+ set(CMAKE_TOOLCHAIN_FILE ${CMAKE_TOOLCHAIN_DIR}/bare-metal-gcc.cmake
+ CACHE FILEPATH "Toolchain file")
+ endif()
+
+ # Arm Corstone-315's timing adapter behaviour is very different to Arm Corstone-300 and cannot
+ # be used for bandwidth/latency related performance sweeps for the Arm Ethos-U NPU. Read
+ # docs/sections/timing_adapters.md for more details.
+ if ((TARGET_SUBSYSTEM STREQUAL "sse-315") AND (DEFINED ETHOS_U_NPU_TIMING_ADAPTER_ENABLED))
+ message(STATUS "Timing adapter will NOT be used for target subsystem ${TARGET_SUBSYSTEM}")
+ set(ETHOS_U_NPU_TIMING_ADAPTER_ENABLED OFF CACHE BOOL "Use of TA" FORCE)
+ endif()
+
+ set(LINKER_SCRIPT_NAME "mps4-${TARGET_SUBSYSTEM}" PARENT_SCOPE)
+ set(PLATFORM_DRIVERS_DIR "${HAL_PLATFORM_DIR}/mps4" PARENT_SCOPE)
+
+endfunction()
+
+function(platform_custom_post_build)
+ set(oneValueArgs TARGET_NAME)
+ cmake_parse_arguments(PARSED "" "${oneValueArgs}" "" ${ARGN} )
+
+ set_target_properties(${PARSED_TARGET_NAME} PROPERTIES SUFFIX ".axf")
+
+ # Add link options for the linker script to be used:
+ add_linker_script(
+ ${PARSED_TARGET_NAME} # Target
+ ${CMAKE_SCRIPTS_DIR}/platforms/mps4/${TARGET_SUBSYSTEM} # Directory path
+ ${LINKER_SCRIPT_NAME}) # Name of the file without suffix
+
+ add_target_map_file(
+ ${PARSED_TARGET_NAME}
+ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PARSED_TARGET_NAME}.map)
+
+ set(SECTORS_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/sectors)
+ set(SECTORS_BIN_DIR ${SECTORS_DIR}/${use_case})
+
+ file(REMOVE_RECURSE ${SECTORS_BIN_DIR})
+ file(MAKE_DIRECTORY ${SECTORS_BIN_DIR})
+
+ if (TARGET_SUBSYSTEM STREQUAL sse-315)
+ set(LINKER_SECTION_TAGS "*.at_itcm" "*.at_ddr")
+ set(LINKER_OUTPUT_BIN_TAGS "itcm.bin" "ddr.bin")
+ endif()
+
+ add_bin_generation_command(
+ TARGET_NAME ${PARSED_TARGET_NAME}
+ OUTPUT_DIR ${SECTORS_BIN_DIR}
+ AXF_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PARSED_TARGET_NAME}.axf
+ SECTION_PATTERNS "${LINKER_SECTION_TAGS}"
+ OUTPUT_BIN_NAMES "${LINKER_OUTPUT_BIN_TAGS}")
+
+ set(MPS4_FPGA_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/scripts/mps4/${TARGET_SUBSYSTEM}/images.txt")
+
+ add_custom_command(TARGET ${PARSED_TARGET_NAME}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${MPS4_FPGA_CONFIG} ${SECTORS_DIR})
+
+ # Add tests for application on FVP if FVP path specified
+ if (BUILD_FVP_TESTS)
+
+ # Build for all use cases if USE_SINGLE_INPUT as no telnet interaction required
+ # otherwise only build for inference runner
+ if ((USE_SINGLE_INPUT) OR (${use_case} STREQUAL "inference_runner"))
+ set(AXF_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PARSED_TARGET_NAME}.axf")
+ set(TEST_TARGET_NAME "${use_case}_fvp_test")
+
+ message(STATUS "Adding FVP test for ${use_case}")
+
+ add_test(
+ NAME "${TEST_TARGET_NAME}"
+ COMMAND ${FVP_PATH} -a ${AXF_PATH}
+ -C mps4_board.telnetterminal0.start_telnet=0
+ -C mps4_board.uart0.out_file='-'
+ -C mps4_board.uart0.shutdown_on_eot=1
+ -C mps4_board.visualisation.disable-visualisation=1
+ -C vis_hdlcd.disable_visualisation=1
+ -C mps4_board.subsystem.iotss3_systemcontrol.INITSVTOR_RST=0x12000000
+ --stat)
+ endif()
+ endif ()
+
+endfunction()
diff --git a/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.ld b/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.ld
new file mode 100644
index 0000000..10ead0e
--- /dev/null
+++ b/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.ld
@@ -0,0 +1,218 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+__STACK_SIZE = 0x00008000;
+__HEAP_SIZE = 0x000C0000;
+
+/* System memory brief */
+MEMORY
+{
+ ITCM (rx) : ORIGIN = 0x10000000, LENGTH = 0x00008000
+ DTCM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00008000
+ BOOT (rx) : ORIGIN = 0x11000000, LENGTH = 0x00010000
+ BRAM (rwx) : ORIGIN = 0x12000000, LENGTH = 0x00200000
+ SRAM (rwx) : ORIGIN = 0x31000000, LENGTH = 0x00400000
+ DDR (rwx) : ORIGIN = 0x70000000, LENGTH = 0x02000000
+
+ /* Dynamic load regions declared for use by FVP only
+ * These regions are mentioned in the CMake subsystem profile.
+ * Do not change the addresses here in isolation. */
+ DDR_dynamic_model (rx) : ORIGIN = 0x90000000, LENGTH = 0x02000000
+ DDR_dynamic_ifm (rx) : ORIGIN = 0x92000000, LENGTH = 0x01000000
+ DDR_dynamic_ofm (rx) : ORIGIN = 0x93000000, LENGTH = 0x01000000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions ITCM and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text.at_bram :
+ {
+ KEEP(*(.vectors))
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ KEEP(*(.eh_frame*))
+
+ *(vtable)
+ *(.data)
+ *(.data.*)
+ . = ALIGN(4);
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ . = ALIGN(4);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ . = ALIGN(4);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ . = ALIGN(4);
+
+ *(.rodata*)
+ . = ALIGN(4);
+ * (npu_driver_version)
+ . = ALIGN(4);
+ * (npu_driver_arch_version)
+ . = ALIGN(4);
+
+ __copy_table_start__ = .;
+ . = ALIGN(4);
+ __copy_table_end__ = .;
+ } > BRAM
+
+ __exidx_start = .;
+ .ARM.exidx.at_bram :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > BRAM
+ __exidx_end = .;
+
+ .sram :
+ {
+ . = ALIGN(16);
+ /* Cache area (if used) */
+ *(.bss.NoInit.ethos_u_cache)
+ . = ALIGN (16);
+ /* activation buffers a.k.a tensor arena when memory mode sram only or shared sram */
+ *(.bss.NoInit.activation_buf_sram)
+ . = ALIGN(16);
+ } > SRAM AT > SRAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > BRAM
+
+ .zero.table.at_bram :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+
+ LONG (__bss_start__)
+ LONG ((__bss_end__ - __bss_start__)/4) /* Size is in 32-bit words */
+
+ __zero_table_end__ = .;
+ } > BRAM
+
+ .heap (COPY) :
+ {
+ . = ALIGN(8);
+ __end__ = .;
+ PROVIDE(end = .);
+ . = . + __HEAP_SIZE;
+ . = ALIGN(8);
+ __HeapLimit = .;
+ } > BRAM
+
+ __bram_total = ALIGN(4);
+
+ ASSERT( __bram_total < (ORIGIN(BRAM) + LENGTH(BRAM)), "BRAM overflow")
+
+ .stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) :
+ {
+ . = ALIGN(8);
+ __StackLimit = .;
+ . = . + __STACK_SIZE;
+ . = ALIGN(8);
+ __StackTop = .;
+ } > DTCM
+ PROVIDE(__stack = __StackTop);
+ ASSERT(__STACK_SIZE <= LENGTH(DTCM), "DTCM overflow")
+
+ .ddr.at_ddr :
+ {
+ /* __attribute__((aligned(16))) is not handled by the CMSIS startup code.
+ * Force the alignment here as a workaround */
+ . = ALIGN(16);
+ /* nn model's baked in input matrices */
+ *(ifm)
+ . = ALIGN(16);
+ /* nn model's default space */
+ *(nn_model)
+ . = ALIGN (16);
+ /* labels */
+ *(labels)
+ . = ALIGN (16);
+ *Labels*.obj (*.rodata*)
+ . = ALIGN (16);
+ /* activation buffers a.k.a tensor arena when memory mode dedicated sram */
+ *(activation_buf_dram)
+ . = ALIGN (16);
+ } > DDR AT > DDR
+
+}
diff --git a/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.sct b/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.sct
new file mode 100644
index 0000000..4451f21
--- /dev/null
+++ b/scripts/cmake/platforms/mps4/sse-315/mps4-sse-315.sct
@@ -0,0 +1,143 @@
+; SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
+; SPDX-License-Identifier: Apache-2.0
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+; *************************************************************
+; *** Scatter-Loading Description File ***
+; *************************************************************
+; Please see docs/sections/appendix.md for memory mapping
+; information.
+;
+; Note: Ethos-U NPU can access BRAM, internal SRAM and the DDR
+; sections => activation buffers and the model should
+; only be placed in those regions.
+;
+
+;---------------------------------------------------------
+; First load region (FPGA SRAM) 2MiB region
+; NOTE: The default INITSVTOR is 0x11000000 and not the
+; ITCM (32K) which we do not use for any code, but
+; could potentially put some critical code in there
+; if we need to.
+; @TODO: The memory pointed to by the INITSVTOR is a 64
+; kiB location for boot code which we should use.
+;---------------------------------------------------------
+LOAD_REGION_0 0x12000000 0x00200000
+{
+ ;-----------------------------------------------------
+ ; First 640K of FGPA SRAM.
+ ;-----------------------------------------------------
+ bram.bin 0x12000000 0x000A0000
+ {
+ *.o (RESET, +First)
+ * (InRoot$$Sections)
+
+ ; Essentially only RO (code + data)
+ .ANY (+RO)
+ }
+
+ ;-----------------------------------------------------
+ ; Next 384K of SRAM/BRAM region for RO, RW and ZI
+ ; data, 8 byte aligned.
+ ;-----------------------------------------------------
+ data.bin 0x120A0000 ALIGN 8 0x00060000
+ {
+ ; Any RO-DATA
+ .ANY (+RO-DATA)
+
+ ; Any R/W and/or zero initialised data
+ .ANY(+RW +ZI)
+ }
+
+ ;-----------------------------------------------------
+ ; 768 KiB of remaining part of the 1MiB BRAM used as
+ ; heap space.
+ ;-----------------------------------------------------
+ ARM_LIB_HEAP 0x12100000 EMPTY ALIGN 8 0x000C0000
+ {}
+
+ ;-----------------------------------------------------
+ ; 32 kiB of stack space occupying the DTCM region.
+ ;-----------------------------------------------------
+ ARM_LIB_STACK 0x30000000 EMPTY ALIGN 8 0x00008000
+ {}
+
+ ;-----------------------------------------------------
+ ; FPGA internal SRAM of 2MiB - reserved for activation
+ ; buffers. The total memory is 4 MiB (we are choosing
+ ; to not use the other bank). This region should have
+ ; 3 cycle read latency from both CPU and Ethos-U NPU.
+ ;-----------------------------------------------------
+ isram.bin 0x31000000 UNINIT ALIGN 16 0x00200000
+ {
+ ; Cache area (if used)
+ *.o (.bss.NoInit.ethos_u_cache)
+
+ ; activation buffers a.k.a tensor arena when
+ ; memory mode sram only or shared sram
+ *.o (.bss.NoInit.activation_buf_sram)
+ }
+}
+
+;---------------------------------------------------------
+; Second load region (DDR)
+;---------------------------------------------------------
+LOAD_REGION_1 0x70000000 0x02000000
+{
+ ;-----------------------------------------------------
+ ; 32 MiB of DDR space for neural network model,
+ ; input vectors and labels. If the activation buffer
+ ; size required by the network is bigger than the
+ ; SRAM size available, it is accommodated here.
+ ;-----------------------------------------------------
+ ddr.bin 0x70000000 ALIGN 16 0x02000000
+ {
+ ; nn model's baked in input matrices
+ *.o (ifm)
+
+ ; nn model's default space
+ *.o (nn_model)
+
+ ; labels
+ *.o (labels)
+ Labels.o (+RO-DATA)
+
+ ; activation buffers a.k.a tensor arena when memory mode dedicated sram
+ *.o (activation_buf_dram)
+ }
+
+ ;-----------------------------------------------------
+ ; The following regions are for use by the FVP to
+ ; allow loading or dumping of dynamic data into or
+ ; from the memory. These regions are mentioned in
+ ; the CMake subsystem profile. Do not change the
+ ; addresses and sizes below in isolation.
+ ;-----------------------------------------------------
+ ; 32 MiB of model space for run-time load of model
+ ;-----------------------------------------------------
+ runtime_model 0x90000000 EMPTY ALIGN 16 0x02000000
+ {}
+
+ ;-----------------------------------------------------
+ ; 16 MiB of IFM space for run-time loading (FVP only)
+ ;-----------------------------------------------------
+ runtime_ifm 0x92000000 EMPTY ALIGN 16 0x01000000
+ {}
+
+ ;-----------------------------------------------------
+ ; 16 MiB of OFM space for run-time loading (FVP only)
+ ;-----------------------------------------------------
+ runtime_ofm 0x93000000 EMPTY ALIGN 16 0x01000000
+ {}
+}
diff --git a/scripts/cmake/platforms/platforms-preset.json b/scripts/cmake/platforms/platforms-preset.json
index 7a96d7a..b38739c 100644
--- a/scripts/cmake/platforms/platforms-preset.json
+++ b/scripts/cmake/platforms/platforms-preset.json
@@ -8,7 +8,7 @@
"configurePresets": [
{
"name": "mps3-300-platform",
- "description": "Target mps3 board, SSE-300 subsystem.",
+ "description": "Target MPS3 board, SSE-300 subsystem.",
"hidden": true,
"cacheVariables": {
"TARGET_PLATFORM": {
@@ -23,7 +23,7 @@
},
{
"name": "mps3-310-platform",
- "description": "Target mps3 board, SSE-310 subsystem.",
+ "description": "Target MPS3 board, SSE-310 subsystem.",
"hidden": true,
"cacheVariables": {
"TARGET_PLATFORM": {
@@ -37,6 +37,21 @@
}
},
{
+ "name": "mps4-315-platform",
+ "description": "Target MPS4 board, SSE-315 subsystem.",
+ "hidden": true,
+ "cacheVariables": {
+ "TARGET_PLATFORM": {
+ "type": "STRING",
+ "value": "mps4"
+ },
+ "TARGET_SUBSYSTEM": {
+ "type": "STRING",
+ "value": "sse-315"
+ }
+ }
+ },
+ {
"name": "simple-platform",
"description": "Target simple platform.",
"hidden": true,
diff --git a/scripts/mps4/sse-315/images.txt b/scripts/mps4/sse-315/images.txt
new file mode 100644
index 0000000..960f2b7
--- /dev/null
+++ b/scripts/mps4/sse-315/images.txt
@@ -0,0 +1,14 @@
+TITLE: Arm MPS3 FPGA prototyping board Images Configuration File
+
+[IMAGES]
+TOTALIMAGES: 2 ;Number of Images (Max: 32)
+
+IMAGE0PORT: 1
+IMAGE0ADDRESS: 0x00_1200_0000 ; Address to load into
+IMAGE0UPDATE: RAM ; Image Update:NONE/AUTO/FORCE
+IMAGE0FILE: \SOFTWARE\bram.bin ; Image/data to be loaded
+
+IMAGE1PORT: 1
+IMAGE1ADDRESS: 0x00_7000_0000 ; Address to load into
+IMAGE1UPDATE: RAM ; Image Update:NONE/AUTO/FORCE
+IMAGE1FILE: \SOFTWARE\ddr.bin ; Image/data to be loaded
diff --git a/source/application/main/Main.cc b/source/application/main/Main.cc
index bbe35d9..08ac978 100644
--- a/source/application/main/Main.cc
+++ b/source/application/main/Main.cc
@@ -1,5 +1,6 @@
/*
- * SPDX-FileCopyrightText: Copyright 2021-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,7 +37,7 @@ static void print_application_intro()
{
info("%s\n", PRJ_DES_STR);
info("Version %s Build date: " __DATE__ " @ " __TIME__ "\n", PRJ_VER_STR);
- info("Copyright 2021-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n\n");
+ info("Copyright 2021-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>\n\n");
}
int main ()
diff --git a/source/hal/source/platform/mps4/CMakeLists.txt b/source/hal/source/platform/mps4/CMakeLists.txt
new file mode 100644
index 0000000..679d5b3
--- /dev/null
+++ b/source/hal/source/platform/mps4/CMakeLists.txt
@@ -0,0 +1,150 @@
+#----------------------------------------------------------------------------
+# SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+# affiliates <open-source-office@arm.com>
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#----------------------------------------------------------------------------
+
+#########################################################
+# MPS4 platform support library #
+#########################################################
+
+cmake_minimum_required(VERSION 3.21.0)
+set(PLATFORM_DRIVERS_TARGET platform_drivers)
+project(${PLATFORM_DRIVERS_TARGET}
+ DESCRIPTION "Platform drivers library for MPS4 FPGA/FVP targets"
+ LANGUAGES C CXX ASM)
+
+# 1. We should be cross-compiling (MPS4 target only runs Cortex-M targets)
+if (NOT ${CMAKE_CROSSCOMPILING})
+ message(FATAL_ERROR "No ${PLATFORM_DRIVERS_TARGET} support for this target.")
+endif()
+# Define target specific base addresses here (before adding the components)
+if (TARGET_SUBSYSTEM STREQUAL sse-315)
+ set(UART0_BASE "0x48203000" CACHE STRING "UART base address")
+ set(UART0_BAUDRATE "115200" CACHE STRING "UART baudrate")
+ set(SYSTEM_CORE_CLOCK "25000000" CACHE STRING "System peripheral clock (Hz)")
+
+ set(ETHOS_U_IRQN "16" CACHE STRING "Ethos-U Interrupt")
+ set(ETHOS_U_SEC_ENABLED "1" CACHE STRING "Ethos-U NPU Security enable")
+ set(ETHOS_U_PRIV_ENABLED "1" CACHE STRING "Ethos-U NPU Privilege enable")
+
+ if (ETHOS_U_SEC_ENABLED)
+ set(ETHOS_U_BASE_ADDR "0x50004000" CACHE STRING "Ethos-U NPU base address")
+ else ()
+ set(ETHOS_U_BASE_ADDR "0x40004000" CACHE STRING "Ethos-U NPU base address")
+ endif ()
+
+ if (ETHOS_U_NPU_TIMING_ADAPTER_ENABLED)
+ message(FATAL_ERROR "Timing adapter support should be disabled for ${TARGET_SUBSYSTEM}")
+ endif()
+endif()
+
+set(DYNAMIC_MODEL_BASE "0x90000000" CACHE STRING "Region to be used for dynamic load of model into memory")
+set(DYNAMIC_MODEL_SIZE "0x02000000" CACHE STRING "Size of the space reserved for the model")
+
+math(EXPR IFM_BASE "${DYNAMIC_MODEL_BASE} + ${DYNAMIC_MODEL_SIZE}" OUTPUT_FORMAT HEXADECIMAL)
+set(DYNAMIC_IFM_BASE "${IFM_BASE}" CACHE STRING "Base address for IFMs to be loaded")
+set(DYNAMIC_IFM_SIZE "0x01000000" CACHE STRING "Size of the space reserved for the IFM")
+math(EXPR OFM_BASE "${DYNAMIC_IFM_BASE} + ${DYNAMIC_IFM_SIZE}" OUTPUT_FORMAT HEXADECIMAL)
+set(DYNAMIC_OFM_BASE "${OFM_BASE}" CACHE STRING "Base address for OFMs to be dumped to")
+set(DYNAMIC_OFM_SIZE "0x01000000" CACHE STRING "Size of the space reserved for the OFM")
+
+
+# 2. Create static library
+add_library(${PLATFORM_DRIVERS_TARGET} STATIC)
+
+## Include directories - private
+target_include_directories(${PLATFORM_DRIVERS_TARGET}
+ PRIVATE
+ source)
+
+## Include directories - public
+target_include_directories(${PLATFORM_DRIVERS_TARGET}
+ PUBLIC
+ include
+ include/${TARGET_SUBSYSTEM})
+
+## Platform sources
+target_sources(${PLATFORM_DRIVERS_TARGET}
+ PRIVATE
+ source/timer_mps4.c
+ source/platform_drivers.c)
+
+## Directory for additional components required by MPS4:
+if (NOT DEFINED COMPONENTS_DIR)
+ set(COMPONENTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../components)
+endif()
+
+## Platform component: cmsis_device (provides generic Cortex-M start up library)
+add_subdirectory(${COMPONENTS_DIR}/cmsis_device ${CMAKE_BINARY_DIR}/cmsis_device)
+
+## Platform component: stdout
+set(STDOUT_RETARGET ON CACHE BOOL "Retarget stdout/err to UART")
+add_subdirectory(${COMPONENTS_DIR}/stdout ${CMAKE_BINARY_DIR}/stdout)
+
+## Platform component: lcd
+add_subdirectory(${COMPONENTS_DIR}/lcd ${CMAKE_BINARY_DIR}/lcd)
+
+## Platform component: PMU
+add_subdirectory(${COMPONENTS_DIR}/platform_pmu ${CMAKE_BINARY_DIR}/platform_pmu)
+
+## Logging utilities:
+if (NOT TARGET log)
+ if (NOT DEFINED LOG_PROJECT_DIR)
+ message(FATAL_ERROR "LOG_PROJECT_DIR needs to be defined.")
+ endif()
+ add_subdirectory(${LOG_PROJECT_DIR} ${CMAKE_BINARY_DIR}/log)
+endif()
+
+# Add dependencies:
+target_link_libraries(${PLATFORM_DRIVERS_TARGET} PUBLIC
+ log
+ cmsis_device
+ platform_pmu
+ lcd_stubs
+ $<IF:$<BOOL:STDOUT_RETARGET>,stdout_retarget_cmsdk,stdout>)
+
+# Set the CPU profiling definition
+if (CPU_PROFILE_ENABLED)
+ target_compile_definitions(${PLATFORM_DRIVERS_TARGET} PUBLIC CPU_PROFILE_ENABLED)
+endif()
+
+# If Ethos-U is enabled, we need the driver library too
+if (ETHOS_U_NPU_ENABLED)
+
+ ## Platform component: Ethos-U initialization
+ add_subdirectory(${COMPONENTS_DIR}/npu ${CMAKE_BINARY_DIR}/npu)
+
+ target_link_libraries(${PLATFORM_DRIVERS_TARGET}
+ PUBLIC
+ ethos_u_npu)
+
+ if (ETHOS_U_NPU_TIMING_ADAPTER_ENABLED)
+ ## Platform component: Ethos-U timing adapter initialization
+ add_subdirectory(${COMPONENTS_DIR}/npu_ta ${CMAKE_BINARY_DIR}/npu_ta)
+
+ target_link_libraries(${PLATFORM_DRIVERS_TARGET}
+ PUBLIC
+ ethos_u_ta)
+ endif()
+
+endif()
+
+# 3. Display status:
+message(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR})
+message(STATUS "*******************************************************")
+message(STATUS "Library : " ${PLATFORM_DRIVERS_TARGET})
+message(STATUS "CMAKE_SYSTEM_PROCESSOR : " ${CMAKE_SYSTEM_PROCESSOR})
+message(STATUS "*******************************************************")
diff --git a/source/hal/source/platform/mps4/include/platform_drivers.h b/source/hal/source/platform/mps4/include/platform_drivers.h
new file mode 100644
index 0000000..d3060de
--- /dev/null
+++ b/source/hal/source/platform/mps4/include/platform_drivers.h
@@ -0,0 +1,47 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PLATFORM_DRIVERS_H
+#define PLATFORM_DRIVERS_H
+
+#include "log_macros.h" /* Logging related helpers. */
+
+/* Platform components */
+#include "RTE_Components.h" /* For CPU related defintiions */
+#include "timer_mps4.h" /* Timer functions. */
+#include "user_input.h" /* User input function */
+#include "lcd_img.h" /* LCD functions. */
+
+/**
+ * @brief Initialises the platform components.
+ * @return 0 if successful, error code otherwise.
+ */
+int platform_init(void);
+
+/**
+ * @brief Teardown for platform components.
+ */
+void platform_release(void);
+
+/**
+ * @brief Gets the platform name.
+ * @return Pointer to the name
+ */
+const char* platform_name(void);
+
+#endif /* PLATFORM_DRIVERS_H */
diff --git a/source/hal/source/platform/mps4/include/sse-315/mem_regions.h b/source/hal/source/platform/mps4/include/sse-315/mem_regions.h
new file mode 100644
index 0000000..8fc111b
--- /dev/null
+++ b/source/hal/source/platform/mps4/include/sse-315/mem_regions.h
@@ -0,0 +1,124 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEM_REGION_DEFS_H
+#define MEM_REGION_DEFS_H
+
+/** Sizes */
+#define ITCM_SIZE (0x00080000) /* ITCM size */
+#define DTCM_BLK_SIZE (0x00020000) /* DTCM size, 4 banks of this size available */
+#define BRAM_SIZE (0x00200000) /* BRAM size */
+#define ISRAM0_SIZE (0x00200000) /* ISRAM0 size */
+#define ISRAM1_SIZE (0x00200000) /* ISRAM1 size */
+#define QSPI_SRAM_SIZE (0x00800000) /* QSPI Flash size */
+#define DDR4_BLK_SIZE (0x10000000) /* DDR4 block size */
+
+/** Non-secure addresses */
+#define ITCM_BASE_NS (0x00000000) /* Instruction TCM Non-Secure base address */
+#define BRAM_BASE_NS (0x01000000) /* FPGA SRAM Non-Secure base address */
+#define DTCM0_BASE_NS (0x20000000) /* Data TCM block 0 Non-Secure base address */
+#define DTCM1_BASE_NS (0x20020000) /* Data TCM block 1 Non-Secure base address */
+#define DTCM2_BASE_NS (0x20040000) /* Data TCM block 2 Non-Secure base address */
+#define DTCM3_BASE_NS (0x20060000) /* Data TCM block 3 Non-Secure base address */
+#define ISRAM0_BASE_NS (0x21000000) /* Internal SRAM Area Non-Secure base address */
+#define ISRAM1_BASE_NS (0x21200000) /* Internal SRAM Area Non-Secure base address */
+#define QSPI_SRAM_BASE_NS (0x28000000) /* QSPI SRAM Non-Secure base address */
+#define DDR4_BLK0_BASE_NS (0x60000000) /* DDR4 block 0 Non-Secure base address */
+#define DDR4_BLK1_BASE_NS (0x80000000) /* DDR4 block 1 Non-Secure base address */
+#define DDR4_BLK2_BASE_NS (0xA0000000) /* DDR4 block 2 Non-Secure base address */
+#define DDR4_BLK3_BASE_NS (0xC0000000) /* DDR4 block 3 Non-Secure base address */
+
+/** Secure addresses */
+#define ITCM_BASE_S (0x10000000) /* Instruction TCM Secure base address */
+#define BRAM_BASE_S (0x12000000) /* FPGA SRAM Secure base address */
+#define DTCM0_BASE_S (0x30000000) /* Data TCM block 0 Secure base address */
+#define DTCM1_BASE_S (0x30020000) /* Data TCM block 1 Secure base address */
+#define DTCM2_BASE_S (0x30040000) /* Data TCM block 2 Secure base address */
+#define DTCM3_BASE_S (0x30060000) /* Data TCM block 3 Secure base address */
+#define ISRAM0_BASE_S (0x31000000) /* Internal SRAM Area Secure base address */
+#define ISRAM1_BASE_S (0x31200000) /* Internal SRAM Area Secure base address */
+#define DDR4_BLK0_BASE_S (0x70000000) /* DDR4 block 0 Secure base address */
+#define DDR4_BLK1_BASE_S (0x90000000) /* DDR4 block 1 Secure base address */
+#define DDR4_BLK2_BASE_S (0xB0000000) /* DDR4 block 2 Secure base address */
+#define DDR4_BLK3_BASE_S (0xD0000000) /* DDR4 block 3 Secure base address */
+
+/** All VMs use the same MPC block size as defined by VMMPCBLKSIZE. */
+#define SRAM_MPC_BLK_SIZE (0x4000) /* 16 kB */
+#define QSPI_MPC_BLK_SIZE (0x40000) /* 256 kB */
+#define DDR4_MPC_BLK_SIZE (0x100000) /* 1 MB */
+
+/** Defines for Driver MPC's */
+/** SRAM -- 2 MB */
+#define MPC_SRAM_RANGE_BASE_NS (SRAM_BASE_NS)
+#define MPC_SRAM_RANGE_LIMIT_NS (SRAM_BASE_NS + SRAM_SIZE-1)
+#define MPC_SRAM_RANGE_OFFSET_NS (0x0)
+#define MPC_SRAM_RANGE_BASE_S (SRAM_BASE_S)
+#define MPC_SRAM_RANGE_LIMIT_S (SRAM_BASE_S + SRAM_SIZE-1)
+#define MPC_SRAM_RANGE_OFFSET_S (0x0)
+
+/** QSPI -- 8 MB */
+#define MPC_QSPI_RANGE_BASE_NS (QSPI_SRAM_BASE_NS)
+#define MPC_QSPI_RANGE_LIMIT_NS (QSPI_SRAM_BASE_NS + QSPI_SRAM_SIZE-1)
+#define MPC_QSPI_RANGE_OFFSET_NS (0x0)
+#define MPC_QSPI_RANGE_BASE_S (QSPI_SRAM_BASE_S)
+#define MPC_QSPI_RANGE_LIMIT_S (QSPI_SRAM_BASE_S + QSPI_SRAM_SIZE-1)
+#define MPC_QSPI_RANGE_OFFSET_S (0x0)
+
+/** ISRAM0 -- 2 MB*/
+#define MPC_ISRAM0_RANGE_BASE_NS (ISRAM0_BASE_NS)
+#define MPC_ISRAM0_RANGE_LIMIT_NS (ISRAM0_BASE_NS + ISRAM0_SIZE-1)
+#define MPC_ISRAM0_RANGE_OFFSET_NS (0x0)
+#define MPC_ISRAM0_RANGE_BASE_S (ISRAM0_BASE_S)
+#define MPC_ISRAM0_RANGE_LIMIT_S (ISRAM0_BASE_S + ISRAM0_SIZE-1)
+#define MPC_ISRAM0_RANGE_OFFSET_S (0x0)
+
+/** ISRAM1 -- 2 MB */
+#define MPC_ISRAM1_RANGE_BASE_NS (ISRAM1_BASE_NS)
+#define MPC_ISRAM1_RANGE_LIMIT_NS (ISRAM1_BASE_NS + ISRAM1_SIZE-1)
+#define MPC_ISRAM1_RANGE_OFFSET_NS (0x0)
+#define MPC_ISRAM1_RANGE_BASE_S (ISRAM1_BASE_S)
+#define MPC_ISRAM1_RANGE_LIMIT_S (ISRAM1_BASE_S + ISRAM1_SIZE-1)
+#define MPC_ISRAM1_RANGE_OFFSET_S (0x0)
+
+/** DDR4 -- 2GB (8 * 256 MB) */
+#define MPC_DDR4_BLK0_RANGE_BASE_NS (DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK0_RANGE_LIMIT_NS (DDR4_BLK0_BASE_NS + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK0_RANGE_OFFSET_NS (0x0)
+#define MPC_DDR4_BLK1_RANGE_BASE_S (DDR4_BLK1_BASE_S)
+#define MPC_DDR4_BLK1_RANGE_LIMIT_S (DDR4_BLK1_BASE_S + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK1_RANGE_OFFSET_S (DDR4_BLK1_BASE_S - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK2_RANGE_BASE_NS (DDR4_BLK2_BASE_NS)
+#define MPC_DDR4_BLK2_RANGE_LIMIT_NS (DDR4_BLK2_BASE_NS + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK2_RANGE_OFFSET_NS (DDR4_BLK2_BASE_NS - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK3_RANGE_BASE_S (DDR4_BLK3_BASE_S)
+#define MPC_DDR4_BLK3_RANGE_LIMIT_S (DDR4_BLK3_BASE_S + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK3_RANGE_OFFSET_S (DDR4_BLK3_BASE_S - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK4_RANGE_BASE_NS (DDR4_BLK4_BASE_NS)
+#define MPC_DDR4_BLK4_RANGE_LIMIT_NS (DDR4_BLK4_BASE_NS + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK4_RANGE_OFFSET_NS (DDR4_BLK4_BASE_NS - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK5_RANGE_BASE_S (DDR4_BLK5_BASE_S)
+#define MPC_DDR4_BLK5_RANGE_LIMIT_S (DDR4_BLK5_BASE_S + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK5_RANGE_OFFSET_S (DDR4_BLK5_BASE_S - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK6_RANGE_BASE_NS (DDR4_BLK6_BASE_NS)
+#define MPC_DDR4_BLK6_RANGE_LIMIT_NS (DDR4_BLK6_BASE_NS + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK6_RANGE_OFFSET_NS (DDR4_BLK6_BASE_NS - DDR4_BLK0_BASE_NS)
+#define MPC_DDR4_BLK7_RANGE_BASE_S (DDR4_BLK7_BASE_S)
+#define MPC_DDR4_BLK7_RANGE_LIMIT_S (DDR4_BLK7_BASE_S + ((DDR4_BLK_SIZE)-1))
+#define MPC_DDR4_BLK7_RANGE_OFFSET_S (DDR4_BLK7_BASE_S - DDR4_BLK0_BASE_NS)
+
+#endif /* MEM_REGION_DEFS_H */
diff --git a/source/hal/source/platform/mps4/include/sse-315/peripheral_irqs.h b/source/hal/source/platform/mps4/include/sse-315/peripheral_irqs.h
new file mode 100644
index 0000000..e6004b5
--- /dev/null
+++ b/source/hal/source/platform/mps4/include/sse-315/peripheral_irqs.h
@@ -0,0 +1,121 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License)Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing)software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND)either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PERIPHERAL_IRQS_H
+#define PERIPHERAL_IRQS_H
+
+/******************************************************************************/
+/* Peripheral interrupt numbers */
+/******************************************************************************/
+
+/* ------------------- Cortex-M Processor Exceptions Numbers -------------- */
+/* -14 to -1 should be defined by the system header */
+/* ---------------------- Core Specific Interrupt Numbers ------------------*/
+#define NONSEC_WATCHDOG_IRQn (1) /* Non-Secure Watchdog Interrupt */
+#define SLOWCLK_TIMER_IRQn (2) /* SLOWCLK Timer Interrupt */
+#define TIMER0_IRQn (3) /* TIMER 0 Interrupt */
+#define TIMER1_IRQn (4) /* TIMER 1 Interrupt */
+#define TIMER2_IRQn (5) /* TIMER 2 Interrupt */
+
+/** 6,7 and 8 are reserved */
+
+#define MPC_IRQn (9) /* MPC Combined (Secure) Interrupt */
+#define PPC_IRQn (10) /* PPC Combined (Secure) Interrupt */
+#define MSC_IRQn (11) /* MSC Combined (Secure) Interrput */
+#define BRIDGE_ERROR_IRQn (12) /* Bridge Error Combined (Secure) Interrupt*/
+
+/** 13 reserved */
+
+#define Combined_PPU_IRQn (14) /* Combined PPU */
+#define SDC_IRQn (15) /* Secure Debug channel Interrupt */
+#define NPU0_IRQn (16) /* NPU0 i.e., EthosU_IRQn */
+
+/** 17, 18 and 19 are reserved */
+
+#define KMU_IRQn (20) /* KMU Interrupt */
+
+/** 21, 22 and 23 are reserved */
+
+#define DMA_SEC_Combined_IRQn (24) /* DMA Secure Combined Interrupt */
+#define DMA_NONSEC_Combined_IRQn (25) /* DMA Non-Secure Combined Interrupt */
+#define DMA_SECURITY_VIOLATION_IRQn (26) /* DMA Security Violation Interrupt */
+#define TIMER3_AON_IRQn (27) /* TIMER 3 AON Interrupt */
+#define CPU0_CTI_0_IRQn (28) /* CPU0 CTI IRQ 0 */
+#define CPU0_CTI_1_IRQn (29) /* CPU0 CTI IRQ 1 */
+#define SAM_CRITICAL_SEVERITY_FAULT_IRQn (30) /* SAM Critical Severity Fault Interrupt */
+#define SAM_SEVERITY_FAULT_HANDLER_IRQn (31) /* SAM Severity Fault Handler Interrupt */
+
+/** 32 reserved */
+
+#define UARTRX0_IRQn (33) /* UART 0 RX Interrupt */
+#define UARTTX0_IRQn (34) /* UART 0 TX Interrupt */
+#define UARTRX1_IRQn (35) /* UART 1 RX Interrupt */
+#define UARTTX1_IRQn (36) /* UART 1 TX Interrupt */
+#define UARTRX2_IRQn (37) /* UART 2 RX Interrupt */
+#define UARTTX2_IRQn (38) /* UART 2 TX Interrupt */
+#define UARTRX3_IRQn (39) /* UART 3 RX Interrupt */
+#define UARTTX3_IRQn (40) /* UART 3 TX Interrupt */
+#define UARTRX4_IRQn (41) /* UART 4 RX Interrupt */
+#define UARTTX4_IRQn (42) /* UART 4 TX Interrupt */
+#define UART0_Combined_IRQn (43) /* UART 0 Combined Interrupt */
+#define UART1_Combined_IRQn (44) /* UART 1 Combined Interrupt */
+#define UART2_Combined_IRQn (45) /* UART 2 Combined Interrupt */
+#define UART3_Combined_IRQn (46) /* UART 3 Combined Interrupt */
+#define UART4_Combined_IRQn (47) /* UART 4 Combined Interrupt */
+#define UARTOVF_IRQn (48) /* UART 0, 1, 2, 3, 4 & 5 Overflow Interrupt */
+#define ETHERNET_IRQn (49) /* Ethernet Interrupt */
+#define I2S_IRQn (50) /* Audio I2S Interrupt */
+
+/** 51-16 are reserved */
+
+#define DMA_CHANNEL_0_IRQn (57) /* DMA Channel 0 Interrupt */
+#define DMA_CHANNEL_1_IRQn (58) /* DMA Channel 1 Interrupt */
+
+/** 59-68 are reseved */
+
+#define GPIO0_Combined_IRQn (69) /* GPIO 0 Combined Interrupt */
+#define GPIO1_Combined_IRQn (70) /* GPIO 1 Combined Interrupt */
+#define GPIO2_Combined_IRQn (71) /* GPIO 2 Combined Interrupt */
+#define GPIO3_Combined_IRQn (72) /* GPIO 3 Combined Interrupt */
+
+/** 73-124 are reserved */
+
+#define UARTRX5_IRQn (125) /* UART 5 RX Interrupt */
+#define UARTTX5_IRQn (126) /* UART 5 TX Interrupt */
+
+/** 127 reserved */
+
+#define RTC_IRQn (128) /* RTC Interrupt */
+
+/** 129-131 are reserved */
+
+#define ISP_IRQn (132) /* ISP C55 Interrupt */
+#define HDLCD_IRQn (133) /* HDLCD Interrupt */
+
+/** 134-223 are reserved */
+
+#define ARM_VSI0_IRQn (224) /* VSI 0 Interrupt */
+#define ARM_VSI1_IRQn (225) /* VSI 1 Interrupt */
+#define ARM_VSI2_IRQn (226) /* VSI 2 Interrupt */
+#define ARM_VSI3_IRQn (227) /* VSI 3 Interrupt */
+#define ARM_VSI4_IRQn (228) /* VSI 4 Interrupt */
+#define ARM_VSI5_IRQn (229) /* VSI 5 Interrupt */
+#define ARM_VSI6_IRQn (230) /* VSI 6 Interrupt */
+#define ARM_VSI7_IRQn (231) /* VSI 7 Interrupt */
+
+#endif /* PERIPHERAL_IRQS_H */
diff --git a/source/hal/source/platform/mps4/include/sse-315/peripheral_memmap.h b/source/hal/source/platform/mps4/include/sse-315/peripheral_memmap.h
new file mode 100644
index 0000000..203fb95
--- /dev/null
+++ b/source/hal/source/platform/mps4/include/sse-315/peripheral_memmap.h
@@ -0,0 +1,196 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates
+ * <open-source-office@arm.com> SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PERIPHERAL_MEMMAP_H
+#define PERIPHERAL_MEMMAP_H
+
+#include "mem_regions.h"
+
+#define DESIGN_NAME "Arm Corstone-315"
+
+/** Non-Secure subsystem peripheral region */
+#define DMA_350_BASE_NS 0x40002000 /* DMA350 register block Non-Secure base address */
+#define NPU0_APB_BASE_NS 0x40004000 /* NPU0 APB Non-Secure base address */
+#define CPU0_PWRCTRL_BASE_NS 0x40012000 /* CPU 0 Power Control Block Non-Secure base address */
+#define CPU0_IDENTITY_BASE_NS 0x4001F000 /* CPU 0 Identity Block Non-Secure base address */
+#define CORSTONE315_NSACFG_BASE_NS 0x40080000 /* Corstone-315 Non-Secure Access Configuration Register Block Non-Secure base address */
+
+/** Non-Secure MSTEXPPILL peripheral region */
+#define GPIO0_CMSDK_BASE_NS 0x40100000 /* GPIO 0 Non-Secure base address */
+#define GPIO1_CMSDK_BASE_NS 0x40101000 /* GPIO 1 Non-Secure base address */
+#define GPIO2_CMSDK_BASE_NS 0x40102000 /* GPIO 2 Non-Secure base address */
+#define GPIO3_CMSDK_BASE_NS 0x40103000 /* GPIO 3 Non-Secure base address */
+#define AHB_USER_0_BASE_NS 0x40104000 /* AHB USER 0 Non-Secure base address */
+#define AHB_USER_1_BASE_NS 0x40105000 /* AHB USER 1 Non-Secure base address */
+#define AHB_USER_2_BASE_NS 0x40106000 /* AHB USER 2 Non-Secure base address */
+#define AHB_USER_3_BASE_NS 0x40107000 /* AHB USER 3 Non-Secure base address */
+#define HDLCD_BASE_NS 0x40310000 /* HDLCD Non-Secure base address */
+#define ETHERNET_BASE_NS 0x40400000 /* Ethernet Non-Secure base address */
+#define USB_BASE_NS 0x40500000 /* USB Non-Secure base address */
+#define USER_APB0_BASE_NS 0x40700000 /* User APB 0 Non-Secure base address */
+#define USER_APB1_BASE_NS 0x40701000 /* User APB 1 Non-Secure base address */
+#define USER_APB2_BASE_NS 0x40702000 /* User APB 2 Non-Secure base address */
+#define USER_APB3_BASE_NS 0x40703000 /* User APB 3 Non-Secure base address */
+#define QSPI_CONFIG_BASE_NS 0x40800000 /* QSPI Config Non-Secure base address */
+#define QSPI_WRITE_BASE_NS 0x40801000 /* QSPI Write Non-Secure base address */
+
+/** Non-Secure subsystem peripheral region */
+#define SYSTIMER0_ARMV8_M_BASE_NS 0x48000000 /* System Timer 0 Non-Secure base address */
+#define SYSTIMER1_ARMV8_M_BASE_NS 0x48001000 /* System Timer 1 Non-Secure base address */
+#define SYSTIMER2_ARMV8_M_BASE_NS 0x48002000 /* System Timer 2 Non-Secure base address */
+#define SYSTIMER3_ARMV8_M_BASE_NS 0x48003000 /* System Timer 3 Non-Secure base address */
+#define CORSTONE315_SYSINFO_BASE_NS 0x48020000 /* Corstone-315 System info Block Non-Secure base address */
+#define SLOWCLK_TIMER_CMSDK_BASE_NS 0x4802F000 /* CMSDK based SLOWCLK Timer Non-Secure base address */
+#define SYSWDOG_ARMV8_M_CNTRL_BASE_NS 0x48040000 /* Non-Secure Watchdog Timer control frame Non-Secure base address */
+#define SYSWDOG_ARMV8_M_REFRESH_BASE_NS 0x48041000 /* Non-Secure Watchdog Timer refresh frame Non-Secure base address */
+#define SYSCNTR_READ_BASE_NS 0x48101000 /* System Counter Read Secure base address */
+
+/** Non-Secure MSTEXPPIHL peripheral region */
+#define FPGA_SBCon_I2C_TOUCH_BASE_NS 0x48100000 /* FPGA - SBCon I2C (Touch) Non-Secure base address */
+#define FPGA_SBCon_I2C_AUDIO_BASE_NS 0x48101000 /* FPGA - SBCon I2C (Audio Conf) Non-Secure base address */
+#define FPGA_SPI_ADC_BASE_NS 0x48102000 /* FPGA - PL022 (SPI ADC) Non-Secure base address */
+#define FPGA_SPI_SHIELD0_BASE_NS 0x48103000 /* FPGA - PL022 (SPI Shield0) Non-Secure base address */
+#define FPGA_SPI_SHIELD1_BASE_NS 0x48104000 /* FPGA - PL022 (SPI Shield1) Non-Secure base address */
+#define SBCon_I2C_SHIELD0_BASE_NS 0x48105000 /* SBCon (I2C - Shield0) Non-Secure base address */
+#define SBCon_I2C_SHIELD1_BASE_NS 0x48106000 /* SBCon (I2C – Shield1) Non-Secure base address */
+#define USER_APB_BASE_NS 0x48107000 /* USER APB Non-Secure base address */
+#define FPGA_DDR4_EEPROM_BASE_NS 0x48108000 /* FPGA - SBCon I2C (DDR4 EEPROM) Non-Secure base address */
+#define FPGA_SCC_BASE_NS 0x48200000 /* FPGA - SCC registers Non-Secure base address */
+#define FPGA_I2S_BASE_NS 0x48201000 /* FPGA - I2S (Audio) Non-Secure base address */
+#define FPGA_IO_BASE_NS 0x48202000 /* FPGA - IO (System Ctrl + I/O) Non-Secure base address */
+#define UART0_BASE_NS 0x48203000 /* UART 0 Non-Secure base address */
+#define UART1_BASE_NS 0x48204000 /* UART 1 Non-Secure base address */
+#define UART2_BASE_NS 0x48205000 /* UART 2 Non-Secure base address */
+#define UART3_BASE_NS 0x48206000 /* UART 3 Non-Secure base address */
+#define UART4_BASE_NS 0x48207000 /* UART 4 Non-Secure base address */
+#define UART5_BASE_NS 0x48208000 /* UART 5 Non-Secure base address */
+#define RTC_BASE_NS 0x4820B000 /* RTC Non-Secure base address */
+#define ISP_BASE_NS 0x48300000 /* ISP SOC base address */
+#define ISP_VIRTUAL_CAMERA_BASE_NS 0x48400000 /* ISP Virtual Camera base address */
+
+#define VSOCKET_BASE_NS 0x4FEE0000 /*!< VSOCKET Non-Secure base address */
+#define VIO_BASE_NS 0x4FEF0000 /*!< VIO Non-Secure base address */
+#define VSI0_BASE_NS 0x4FF00000 /*!< VSI 0 Non-Secure base address */
+#define VSI1_BASE_NS 0x4FF10000 /*!< VSI 1 Non-Secure base address */
+#define VSI2_BASE_NS 0x4FF20000 /*!< VSI 2 Non-Secure base address */
+#define VSI3_BASE_NS 0x4FF30000 /*!< VSI 3 Non-Secure base address */
+#define VSI4_BASE_NS 0x4FF40000 /*!< VSI 4 Non-Secure base address */
+#define VSI5_BASE_NS 0x4FF50000 /*!< VSI 5 Non-Secure base address */
+#define VSI6_BASE_NS 0x4FF60000 /*!< VSI 6 Non-Secure base address */
+#define VSI7_BASE_NS 0x4FF70000 /*!< VSI 7 Non-Secure base address */
+
+/** Secure subsystem peripheral region */
+#define DMA_350_BASE_S 0x50002000 /* DMA350 register block Secure base address */
+#define NPU0_APB_BASE_S 0x50004000 /* NPU0 APB Secure base address */
+#define CPU0_SECCTRL_BASE_S 0x50011000 /* CPU 0 Local Security Control Block Secure base address */
+#define CPU0_PWRCTRL_BASE_S 0x50012000 /* CPU 0 Power Control Block Secure base address */
+#define CPU0_IDENTITY_BASE_S 0x5001F000 /* CPU 0 Identity Block Secure base address */
+#define CORSTONE315_SACFG_BASE_S 0x50080000 /* Corstone-315 Secure Access Configuration Register Secure base address */
+#define MPC_ISRAM0_BASE_S 0x50083000 /* Internal SRAM0 Memory Protection Controller Secure base address */
+#define MPC_ISRAM1_BASE_S 0x50084000 /* Internal SRAM1 Memory Protection Controller Secure base address */
+#define CC3XX_BASE_S 0x50094000 /* CryptoCell CC3XX Secure base address */
+#define KMU_BASE_S 0x5009E000 /* KMU Secure base address */
+#define LCM_BASE_S 0x500A0000 /* LCM Secure base address */
+
+/** Secure MSTEXPPILL peripheral region */
+#define GPIO0_CMSDK_BASE_S 0x50100000 /* GPIO 0 Secure base address */
+#define GPIO1_CMSDK_BASE_S 0x50101000 /* GPIO 1 Secure base address */
+#define GPIO2_CMSDK_BASE_S 0x50102000 /* GPIO 2 Secure base address */
+#define GPIO3_CMSDK_BASE_S 0x50103000 /* GPIO 3 Secure base address */
+#define AHB_USER_0_BASE_S 0x50104000 /* AHB USER 0 Secure base address */
+#define AHB_USER_1_BASE_S 0x50105000 /* AHB USER 1 Secure base address */
+#define AHB_USER_2_BASE_S 0x50106000 /* AHB USER 2 Secure base address */
+#define AHB_USER_3_BASE_S 0x50107000 /* AHB USER 3 Secure base address */
+#define HDLCD_BASE_S 0x50310000 /* HDLCD Secure base address */
+#define ETHERNET_BASE_S 0x50400000 /* Ethernet Secure base address */
+#define USB_BASE_S 0x50500000 /* USB Secure base address */
+#define USER_APB0_BASE_S 0x50700000 /* User APB 0 Secure base address */
+#define USER_APB1_BASE_S 0x50701000 /* User APB 1 Secure base address */
+#define USER_APB2_BASE_S 0x50702000 /* User APB 2 Secure base address */
+#define USER_APB3_BASE_S 0x50703000 /* User APB 3 Secure base address */
+#define QSPI_CONFIG_BASE_S 0x50800000 /* QSPI Config Secure base address */
+#define QSPI_WRITE_BASE_S 0x50801000 /* QSPI Write Secure base address */
+#define MPC_SRAM_BASE_S 0x57000000 /* SRAM Memory Protection Controller Secure base address */
+#define MPC_QSPI_BASE_S 0x57001000 /* QSPI Memory Protection Controller Secure base address */
+#define MPC_DDR4_BASE_S 0x57002000 /* DDR4 Memory Protection Controller Secure base address */
+
+/** Secure subsystem peripheral region */
+#define SYSTIMER0_ARMV8_M_BASE_S 0x58000000 /* System Timer 0 Secure base address */
+#define SYSTIMER1_ARMV8_M_BASE_S 0x58001000 /* System Timer 1 Secure base address */
+#define SYSTIMER2_ARMV8_M_BASE_S 0x58002000 /* System Timer 0 Secure base address */
+#define SYSTIMER3_ARMV8_M_BASE_S 0x58003000 /* System Timer 1 Secure base address */
+#define CORSTONE315_SYSINFO_BASE_S 0x58020000 /* Corstone-315 System info Block Secure base address */
+#define CORSTONE315_SYSCTRL_BASE_S 0x58021000 /* Corstone-315 System control Block Secure base address */
+#define CORSTONE315_SYSPPU_BASE_S 0x58022000 /* Corstone-315 System Power Policy Unit Secure base address */
+#define CORSTONE315_CPU0PPU_BASE_S 0x58023000 /* Corstone-315 CPU 0 Power Policy Unit Secure base address */
+#define CORSTONE315_MGMTPPU_BASE_S 0x58028000 /* Corstone-315 Management Power Policy Unit Secure base address */
+#define CORSTONE315_DBGPPU_BASE_S 0x58029000 /* Corstone-315 Debug Power Policy Unit Secure base address */
+#define CORSTONE315_NPU0PPU_BASE_S 0x5802A000 /* Corstone-315 NPU 0 Power Policy Unit Secure base address */
+#define SLOWCLK_WDOG_CMSDK_BASE_S 0x5802E000 /* CMSDK based SLOWCLK Watchdog Secure base address */
+#define SLOWCLK_TIMER_CMSDK_BASE_S 0x5802F000 /* CMSDK based SLOWCLK Timer Secure base address */
+#define SYSWDOG_ARMV8_M_CNTRL_BASE_S 0x58040000 /* Secure Watchdog Timer control frame Secure base address */
+#define SYSWDOG_ARMV8_M_REFRESH_BASE_S 0x58041000 /* Secure Watchdog Timer refresh frame Secure base address */
+#define SAM_BASE_S 0x58042000 /* SAM Secure base address */
+#define SYSCNTR_CNTRL_BASE_S 0x58100000 /* System Counter Control Secure base address */
+#define SYSCNTR_READ_BASE_S 0x58101000 /* System Counter Read Secure base address */
+
+/** Secure MSTEXPPIHL peripheral region */
+#define FPGA_SBCon_I2C_TOUCH_BASE_S 0x58100000 /* FPGA - SBCon I2C (Touch) Secure base address */
+#define FPGA_SBCon_I2C_AUDIO_BASE_S 0x58101000 /* FPGA - SBCon I2C (Audio Conf) Secure base address */
+#define FPGA_SPI_ADC_BASE_S 0x58102000 /* FPGA - PL022 (SPI ADC) Secure base address */
+#define FPGA_SPI_SHIELD0_BASE_S 0x58103000 /* FPGA - PL022 (SPI Shield0) Secure base address */
+#define FPGA_SPI_SHIELD1_BASE_S 0x58104000 /* FPGA - PL022 (SPI Shield1) Secure base address */
+#define SBCon_I2C_SHIELD0_BASE_S 0x58105000 /* SBCon (I2C - Shield0) Secure base address */
+#define SBCon_I2C_SHIELD1_BASE_S 0x58106000 /* SBCon (I2C – Shield1) Secure base address */
+#define USER_APB_BASE_S 0x58107000 /* USER APB Secure base address */
+#define FPGA_DDR4_EEPROM_BASE_S 0x58108000 /* FPGA - SBCon I2C (DDR4 EEPROM) Secure base address */
+#define FPGA_SCC_BASE_S 0x58200000 /* FPGA - SCC registers Secure base address */
+#define FPGA_I2S_BASE_S 0x58201000 /* FPGA - I2S (Audio) Secure base address */
+#define FPGA_IO_BASE_S 0x58202000 /* FPGA - IO (System Ctrl + I/O) Secure base address */
+#define UART0_BASE_S 0x58203000 /* UART 0 Secure base address */
+#define UART1_BASE_S 0x58204000 /* UART 1 Secure base address */
+#define UART2_BASE_S 0x58205000 /* UART 2 Secure base address */
+#define UART3_BASE_S 0x58206000 /* UART 3 Secure base address */
+#define UART4_BASE_S 0x58207000 /* UART 4 Secure base address */
+#define UART5_BASE_S 0x58208000 /* UART 5 Secure base address */
+#define RTC_BASE_S 0x5820B000 /* RTC Secure base address */
+
+#define VSOCKET_BASE_S 0x5FEE0000 /*!< VSOCKET Secure base address */
+#define VIO_BASE_S 0x5FEF0000 /*!< VIO Secure base address */
+#define VSI0_BASE_S 0x5FF00000 /*!< VSI 0 Secure base address */
+#define VSI1_BASE_S 0x5FF10000 /*!< VSI 1 Secure base address */
+#define VSI2_BASE_S 0x5FF20000 /*!< VSI 2 Secure base address */
+#define VSI3_BASE_S 0x5FF30000 /*!< VSI 3 Secure base address */
+#define VSI4_BASE_S 0x5FF40000 /*!< VSI 4 Secure base address */
+#define VSI5_BASE_S 0x5FF50000 /*!< VSI 5 Secure base address */
+#define VSI6_BASE_S 0x5FF60000 /*!< VSI 6 Secure base address */
+#define VSI7_BASE_S 0x5FF70000 /*!< VSI 7 Secure base address */
+
+/* TCM Security Gate register addresses */
+#define ITGU_CTRL_BASE 0xE001E500 /* TGU control register for ITCM */
+#define ITGU_CFG_BASE 0xE001E504 /* TGU configuration register for ITCM */
+#define ITGU_LUTn_BASE 0xE001E510 /* TGU Look Up Table register for ITCM */
+#define DTGU_CTRL_BASE 0xE001E600 /* TGU control register for DTCM */
+#define DTGU_CFG_BASE 0xE001E604 /* TGU configuration register for DTCM */
+#define DTGU_LUTn_BASE 0xE001E610 /* TGU Look Up Table register for DTCM */
+
+/* Memory map addresses exempt from memory attribution by both the SAU and IDAU */
+#define CORSTONE315_EWIC_BASE 0xE0047000 /* External Wakeup Interrupt Controller
+ * Access from Non-secure software is only allowed
+ * if AIRCR.BFHFNMINS is set to 1 */
+
+#endif /* PERIPHERAL_MEMMAP_H */
diff --git a/source/hal/source/platform/mps4/include/timer_mps4.h b/source/hal/source/platform/mps4/include/timer_mps4.h
new file mode 100644
index 0000000..49dc62d
--- /dev/null
+++ b/source/hal/source/platform/mps4/include/timer_mps4.h
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef TIMER_MPS4_H
+#define TIMER_MPS4_H
+
+#include "platform_pmu.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#if defined (ARM_NPU)
+ #include "ethosu_profiler.h" /* Arm Ethos-U NPU profiling functions. */
+#endif /* defined (ARM_NPU) */
+
+/* Container for timestamp up-counters. */
+typedef struct mps4_pmu_counters_ {
+ uint32_t counter_1Hz;
+ uint32_t counter_100Hz;
+
+ /* Running at FPGA clock rate. See get_mps4_core_clock(). */
+ uint32_t counter_fpga;
+
+ /* Running at processor core's internal clock rate, triggered by SysTick. */
+ uint64_t counter_systick;
+} mps4_pmu_counters;
+
+/**
+ * @brief Resets the counters.
+ */
+void platform_reset_counters(void);
+
+/**
+ * @brief Gets the current counter values.
+ * @param[out] Pointer to a pmu_counters object.
+ **/
+void platform_get_counters(pmu_counters* counters);
+
+/**
+ * @brief Gets the MPS4 core clock
+ * @return Clock rate in Hz expressed as 32 bit unsigned integer.
+ */
+uint32_t get_mps4_core_clock(void);
+
+/**
+ * @brief System tick interrupt handler.
+ **/
+void SysTick_Handler(void);
+
+#endif /* TIMER_MPS4_H */
diff --git a/source/hal/source/platform/mps4/readme.md b/source/hal/source/platform/mps4/readme.md
new file mode 100644
index 0000000..2a17638
--- /dev/null
+++ b/source/hal/source/platform/mps4/readme.md
@@ -0,0 +1,3 @@
+## MPS4 platform drivers
+
+Project to provide HAL platform drivers for the Arm MPS4 FPGA/FVP targets.
diff --git a/source/hal/source/platform/mps4/source/platform_drivers.c b/source/hal/source/platform/mps4/source/platform_drivers.c
new file mode 100644
index 0000000..127d9b3
--- /dev/null
+++ b/source/hal/source/platform/mps4/source/platform_drivers.c
@@ -0,0 +1,180 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "platform_drivers.h"
+
+#include "log_macros.h" /* Logging functions */
+#include "uart_stdout.h" /* stdout over UART. */
+#include "smm_mps4.h" /* Memory map for MPS4. */
+
+#if defined(ARM_NPU)
+#include "ethosu_npu_init.h"
+
+#if defined(ETHOS_U_NPU_TIMING_ADAPTER_ENABLED)
+#include "ethosu_ta_init.h"
+#endif /* ETHOS_U_NPU_TIMING_ADAPTER_ENABLED */
+
+#endif /* ARM_NPU */
+
+/**
+ * @brief Checks if the platform is valid by checking
+ * the CPU ID for the FPGA implementation against
+ * the register from the CPU core.
+ * @return 0 if successful, 1 otherwise
+ */
+static int verify_platform(void);
+
+/** Platform name */
+static const char* s_platform_name = DESIGN_NAME;
+
+int platform_init(void)
+{
+ int err = 0;
+
+ SystemCoreClockUpdate(); /* From start up code */
+
+ /* UART init - will enable valid use of printf (stdout
+ * re-directed at this UART (UART0) */
+ UartStdOutInit();
+
+ if (0 != (err = verify_platform())) {
+ return err;
+ }
+
+#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
+ info("Enabling I-cache.\n");
+ SCB_EnableICache();
+#endif /* __ICACHE_PRESENT */
+
+#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ info("Enabling D-cache.\n");
+ SCB_EnableDCache();
+#endif /* __DCACHE_PRESENT */
+
+#if defined(ARM_NPU)
+
+#if defined(ETHOS_U_NPU_TIMING_ADAPTER_ENABLED)
+ /* If the platform has timing adapter blocks along with Ethos-U core
+ * block, initialise them here. */
+ if (0 != (err = arm_ethosu_timing_adapter_init())) {
+ return err;
+ }
+#endif /* ETHOS_U_NPU_TIMING_ADAPTER_ENABLED */
+
+ int state;
+
+ /* If Arm Ethos-U NPU is to be used, we initialise it here */
+ if (0 != (state = arm_ethosu_npu_init())) {
+ return state;
+ }
+
+#endif /* ARM_NPU */
+
+ /* Print target design info */
+ info("Target system design: %s\n", s_platform_name);
+ return 0;
+}
+
+void platform_release(void)
+{
+ __disable_irq();
+}
+
+const char* platform_name(void)
+{
+ return s_platform_name;
+}
+
+#define CREATE_MASK(msb, lsb) (int)(((1U << ((msb) - (lsb) + 1)) - 1) << (lsb))
+#define MASK_BITS(arg, msb, lsb) (int)((arg) & CREATE_MASK(msb, lsb))
+#define EXTRACT_BITS(arg, msb, lsb) (int)(MASK_BITS(arg, msb, lsb) >> (lsb))
+
+static int verify_platform(void)
+{
+ uint32_t id = 0;
+ uint32_t fpgaid = 0;
+ uint32_t apnote = 0;
+ uint32_t rev = 0;
+ uint32_t aid = 0;
+ uint32_t fpga_clk = 0;
+ const uint32_t ascii_A = (uint32_t)('A');
+
+ /* Initialise the LEDs as the switches are */
+ MPS4_FPGAIO->LED = MPS4_FPGAIO->SWITCHES & 0xFF;
+
+ info("Processor internal clock: %" PRIu32 "Hz\n", get_mps4_core_clock());
+
+ /* Get revision information from various registers */
+ rev = MPS4_SCC->CFG_REG4;
+ fpgaid = MPS4_SCC->SCC_ID;
+ aid = MPS4_SCC->SCC_AID;
+ apnote = EXTRACT_BITS(fpgaid, 15, 4);
+ fpga_clk = get_mps4_core_clock();
+
+ info("V2M-MPS4 revision %c\n\n", (char)(rev + ascii_A));
+ info("Application Note AN%" PRIx32 ", Revision %c\n", apnote,
+ (char)(EXTRACT_BITS(aid, 23, 20) + ascii_A));
+ info("MPS4 build %d\n", EXTRACT_BITS(aid, 31, 24));
+ info("MPS4 core clock has been set to: %" PRIu32 "Hz\n", fpga_clk);
+
+ /* Display CPU ID */
+ id = SCB->CPUID;
+ info("CPU ID: 0x%08" PRIx32 "\n", id);
+
+ if(EXTRACT_BITS(id, 15, 8) == 0xD2) {
+ if (EXTRACT_BITS(id, 7, 4) == 3) {
+ info ("CPU: Cortex-M85 r%dp%d\n\n",
+ EXTRACT_BITS(id, 23, 20),EXTRACT_BITS(id, 3, 0));
+#if defined (ARMv81MML_DSP_DP_MVE_FP) || defined (CPU_CORTEX_M85)
+ /* CPU ID should be "0x_41_0f_d2_30" for Cortex-M85 */
+ return 0;
+#endif /* (ARMv81MML_DSP_DP_MVE_FP) || (CPU_CORTEX_M85) */
+ } else if (EXTRACT_BITS(id, 7, 4) == 2) {
+ info ("CPU: Cortex-M55 r%dp%d\n\n",
+ EXTRACT_BITS(id, 23, 20),EXTRACT_BITS(id, 3, 0));
+#if defined (CPU_CORTEX_M55)
+ /* CPU ID should be "0x_41_0f_d2_20" for Cortex-M55 */
+ return 0;
+#endif /* CPU_CORTEX_M55 */
+ } else if (EXTRACT_BITS(id, 7, 4) == 1) {
+ info ("CPU: Cortex-M33 r%dp%d\n\n",
+ EXTRACT_BITS(id, 23, 20),EXTRACT_BITS(id, 3, 0));
+#if defined (CPU_CORTEX_M33)
+ return 0;
+#endif /* CPU_CORTEX_M33 */
+ } else if (EXTRACT_BITS(id, 7, 4) == 0) {
+ info ("CPU: Cortex-M23 r%dp%d\n\n",
+ EXTRACT_BITS(id, 23, 20),EXTRACT_BITS(id, 3, 0));
+ } else {
+ info ("CPU: Cortex-M processor family");
+ }
+ } else if (EXTRACT_BITS(id, 15, 8) == 0xC6) {
+ info ("CPU: Cortex-M%d+ r%dp%d\n\n",
+ EXTRACT_BITS(id, 7, 4), EXTRACT_BITS(id, 23, 20),
+ EXTRACT_BITS(id, 3, 0));
+ } else {
+ info ("CPU: Cortex-M%d r%dp%d\n\n",
+ EXTRACT_BITS(id, 7, 4), EXTRACT_BITS(id, 23, 20),
+ EXTRACT_BITS(id, 3, 0));
+ }
+
+ /* If the CPU is anything other than Arm Cortex-M33, Arm Cortex-M55 or
+ * Arm Cortex-M85, we return 1 */
+ printf_err("CPU mismatch!\n");
+ return 1;
+}
diff --git a/source/hal/source/platform/mps4/source/smm_mps4.h b/source/hal/source/platform/mps4/source/smm_mps4.h
new file mode 100644
index 0000000..374ffbb
--- /dev/null
+++ b/source/hal/source/platform/mps4/source/smm_mps4.h
@@ -0,0 +1,152 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef SMM_MPS4_H
+#define SMM_MPS4_H
+
+#include "peripheral_memmap.h" /* Peripheral memory map definitions. */
+
+#include "RTE_Components.h"
+
+#if defined ( __CC_ARM )
+#pragma anon_unions
+#endif
+
+/** FPGA System Register declaration */
+typedef struct
+{
+ __IO uint32_t LED; /* Offset: 0x000 (R/W) LED connections
+ * [31:2] : Reserved
+ * [1:0] : LEDs
+ */
+ uint32_t RESERVED1[1];
+ __IO uint32_t BUTTON; /* Offset: 0x008 (R/W) Buttons
+ * [31:2] : Reserved
+ * [1:0] : Buttons
+ */
+ uint32_t RESERVED2[1];
+ __IO uint32_t CLK1HZ; /* Offset: 0x010 (R/W) 1Hz up counter */
+ __IO uint32_t CLK100HZ; /* Offset: 0x014 (R/W) 100Hz up counter */
+ __IO uint32_t COUNTER; /* Offset: 0x018 (R/W) Cycle Up Counter
+ * Increments when 32-bit prescale counter reach zero
+ */
+ __IO uint32_t PRESCALE; /* Offset: 0x01C (R/W) Prescaler
+ * Bit[31:0] : reload value for prescale counter
+ */
+ __IO uint32_t PSCNTR; /* Offset: 0x020 (R/W) 32-bit Prescale counter
+ * current value of the pre-scaler counter
+ * The Cycle Up Counter increment when the prescale down counter reach 0
+ * The pre-scaler counter is reloaded with PRESCALE after reaching 0.
+ */
+ uint32_t RESERVED3[1];
+ __IO uint32_t SWITCHES; /* Offset: 0x028 (R/W) Switches
+ * [31:8] : Reserved
+ * [7:0] : Switches
+ */
+ uint32_t RESERVED4[8];
+ __IO uint32_t MISC; /* Offset: 0x04C (R/W) Misc control
+ * [31:10] : Reserved
+ * [9] :
+ * [8] :
+ * [7] : ADC_SPI_nCS
+ * [6] : CLCD_BL_CTRL
+ * [5] : CLCD_RD
+ * [4] : CLCD_RS
+ * [3] : CLCD_RESET
+ * [2] : SHIELD_1_SPI_nCS
+ * [1] : SHIELD_0_SPI_nCS
+ * [0] : CLCD_CS
+ */
+} MPS4_FPGAIO_TypeDef;
+
+/** SCC Register declaration */
+typedef struct
+{
+ __IO uint32_t CFG_REG0; /* Offset: 0x000 (R/W) Remaps block RAM to ZBT
+ * [31:1] : Reserved
+ * [0] 1 : REMAP BlockRam to ZBT
+ */
+ __IO uint32_t LEDS; /* Offset: 0x004 (R/W) Controls the MCC user LEDs
+ * [31:8] : Reserved
+ * [7:0] : MCC LEDs
+ */
+ uint32_t RESERVED0[1];
+ __I uint32_t SWITCHES; /* Offset: 0x00C (R/ ) Denotes the state of the MCC user switches
+ * [31:8] : Reserved
+ * [7:0] : These bits indicate state of the MCC switches
+ */
+ __I uint32_t CFG_REG4; /* Offset: 0x010 (R/ ) Denotes the board revision
+ * [31:4] : Reserved
+ * [3:0] : Used by the MCC to pass PCB revision. 0 = A 1 = B
+ */
+ __I uint32_t CFG_ACLK; /* Offset: 0x014 (R/ ) System Clock
+ */
+ uint32_t RESERVED1[34];
+ __IO uint32_t SYS_CFGDATA_RTN; /* Offset: 0x0A0 (R/W) User data register
+ * [31:0] : Data
+ */
+ __IO uint32_t SYS_CFGDATA_OUT; /* Offset: 0x0A4 (R/W) User data register
+ * [31:0] : Data
+ */
+ __IO uint32_t SYS_CFGCTRL; /* Offset: 0x0A8 (R/W) Control register
+ * [31] : Start (generates interrupt on write to this bit)
+ * [30] : R/W access
+ * [29:26] : Reserved
+ * [25:20] : Function value
+ * [19:12] : Reserved
+ * [11:0] : Device (value of 0/1/2 for supported clocks)
+ */
+ __IO uint32_t SYS_CFGSTAT; /* Offset: 0x0AC (R/W) Contains status information
+ * [31:2] : Reserved
+ * [1] : Error
+ * [0] : Complete
+ */
+ __IO uint32_t RESERVED2[20];
+ __IO uint32_t SCC_DLL; /* Offset: 0x100 (R/W) DLL Lock Register
+ * [31:24] : DLL LOCK MASK[7:0] - Indicate if the DLL locked is masked
+ * [23:16] : DLL LOCK MASK[7:0] - Indicate if the DLLs are locked or unlocked
+ * [15:1] : Reserved
+ * [0] : This bit indicates if all enabled DLLs are locked
+ */
+ uint32_t RESERVED3[957];
+ __I uint32_t SCC_AID; /* Offset: 0xFF8 (R/ ) SCC AID Register
+ * [31:24] : FPGA build number
+ * [23:20] : V2M-MPS4 target board revision (A = 0, B = 1)
+ * [19:11] : Reserved
+ * [10] : if “1” SCC_SW register has been implemented
+ * [9] : if “1” SCC_LED register has been implemented
+ * [8] : if “1” DLL lock register has been implemented
+ * [7:0] : number of SCC configuration register
+ */
+ __I uint32_t SCC_ID; /* Offset: 0xFFC (R/ ) Contains information about the FPGA image
+ * [31:24] : Implementer ID: 0x41 = ARM
+ * [23:20] : Application note IP variant number
+ * [19:16] : IP Architecture: 0x4 =AHB
+ * [15:4] : Primary part number: 386 = AN386
+ * [3:0] : Application note IP revision number
+ */
+} MPS4_SCC_TypeDef;
+
+/** Non-secure peripheral declarations */
+#define MPS4_FPGAIO ((MPS4_FPGAIO_TypeDef *) FPGA_IO_BASE_NS)
+#define MPS4_SCC ((MPS4_SCC_TypeDef *) FPGA_SCC_BASE_NS)
+
+/** Secure peripheral declarations */
+#define MPS4_FPGAIO_S ((MPS4_FPGAIO_TypeDef *) FPGA_IO_BASE_S)
+#define MPS4_SCC_S ((MPS4_SCC_TypeDef *) FPGA_SCC_BASE_S)
+
+#endif /* SMM_MPS4_H */
diff --git a/source/hal/source/platform/mps4/source/timer_mps4.c b/source/hal/source/platform/mps4/source/timer_mps4.c
new file mode 100644
index 0000000..4fc27c7
--- /dev/null
+++ b/source/hal/source/platform/mps4/source/timer_mps4.c
@@ -0,0 +1,230 @@
+/*
+ * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its
+ * affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "timer_mps4.h"
+
+#include "log_macros.h"
+#include "smm_mps4.h" /* Memory map for MPS4. */
+
+static uint64_t cpu_cycle_count = 0; /* 64-bit cpu cycle counter */
+static const char* unit_cycles = "cycles";
+static const char* unit_ms = "milliseconds";
+
+/**
+ * @brief Gets the system tick triggered cycle counter for the CPU.
+ * @return 64-bit counter value.
+ **/
+static uint64_t Get_SysTick_Cycle_Count(void);
+
+/**
+ * SysTick initialisation
+ */
+static int Init_SysTick(void);
+
+/**
+ * @brief Adds one PMU counter to the counters' array
+ * @param value Value of the counter
+ * @param name Name for the given counter
+ * @param unit Unit for the "value"
+ * @param counters Pointer to the counter struct - the one to be populated.
+ * @return true if successfully added, false otherwise
+ */
+static bool add_pmu_counter(
+ uint64_t value,
+ const char* name,
+ const char* unit,
+ pmu_counters* counters);
+
+/**
+ * @brief Gets the evaluated millisecond timestamp from the given MPS4 counter struct.
+ * @param mps4_counters Pointer to the MPS4 counters.
+ * @return microseconds timestamp as 32 bit unsigned integer.
+ */
+static uint32_t get_tstamp_milliseconds(mps4_pmu_counters* mps4_counters);
+
+void platform_reset_counters(void)
+{
+ MPS4_FPGAIO->CLK1HZ = 0;
+ MPS4_FPGAIO->CLK100HZ = 0;
+ MPS4_FPGAIO->COUNTER = 0;
+
+ if (0 != Init_SysTick()) {
+ printf_err("Failed to initialise system tick config\n");
+ }
+ debug("system tick config ready\n");
+
+#if defined (ARM_NPU)
+ ethosu_pmu_init();
+#endif /* defined (ARM_NPU) */
+}
+
+void platform_get_counters(pmu_counters* counters)
+{
+ counters->num_counters = 0;
+ counters->initialised = true;
+ uint32_t i = 0;
+
+#if defined (ARM_NPU)
+ ethosu_pmu_counters npu_counters = ethosu_get_pmu_counters();
+ for (i = 0; i < ETHOSU_PMU_NCOUNTERS; ++i) {
+ add_pmu_counter(
+ npu_counters.npu_evt_counters[i].counter_value,
+ npu_counters.npu_evt_counters[i].name,
+ npu_counters.npu_evt_counters[i].unit,
+ counters);
+ }
+ for (i = 0; i < ETHOSU_DERIVED_NCOUNTERS; ++i) {
+ add_pmu_counter(
+ npu_counters.npu_derived_counters[i].counter_value,
+ npu_counters.npu_derived_counters[i].name,
+ npu_counters.npu_derived_counters[i].unit,
+ counters);
+ }
+ add_pmu_counter(
+ npu_counters.npu_total_ccnt,
+ "NPU TOTAL",
+ unit_cycles,
+ counters);
+#else
+ UNUSED(i);
+#endif /* defined (ARM_NPU) */
+
+#if defined(CPU_PROFILE_ENABLED)
+ mps4_pmu_counters mps4_counters = {
+ .counter_1Hz = MPS4_FPGAIO->CLK1HZ,
+ .counter_100Hz = MPS4_FPGAIO->CLK100HZ,
+ .counter_fpga = MPS4_FPGAIO->COUNTER,
+ .counter_systick = Get_SysTick_Cycle_Count()
+ };
+
+ add_pmu_counter(
+ mps4_counters.counter_systick,
+ "CPU TOTAL",
+ unit_cycles,
+ counters);
+
+ add_pmu_counter(
+ get_tstamp_milliseconds(&mps4_counters),
+ "DURATION",
+ unit_ms,
+ counters);
+#endif /* defined(CPU_PROFILE_ENABLED) */
+
+#if !defined(CPU_PROFILE_ENABLED)
+ UNUSED(get_tstamp_milliseconds);
+ UNUSED(Get_SysTick_Cycle_Count);
+ UNUSED(unit_ms);
+#if !defined(ARM_NPU)
+ UNUSED(unit_cycles);
+ UNUSED(add_pmu_counter);
+#endif /* !defined(ARM_NPU) */
+#endif /* !defined(CPU_PROFILE_ENABLED) */
+}
+
+uint32_t get_mps4_core_clock(void)
+{
+ const uint32_t default_clock = 32000000 /* 32 MHz clock */;
+ static int warned_once = 0;
+ if (0 != MPS4_SCC->CFG_ACLK) {
+ return MPS4_SCC->CFG_ACLK;
+ }
+
+ if (!warned_once) {
+ warn("MPS4_SCC->CFG_ACLK reads 0. Assuming default clock of %" PRIu32 "\n",
+ default_clock);
+ warned_once = 1;
+ }
+ return default_clock;
+}
+
+void SysTick_Handler(void)
+{
+ /* Increment the cycle counter based on load value. */
+ cpu_cycle_count += SysTick->LOAD + 1;
+}
+
+/**
+ * Gets the current SysTick derived counter value
+ */
+static uint64_t Get_SysTick_Cycle_Count(void)
+{
+ uint32_t systick_val;
+
+ NVIC_DisableIRQ(SysTick_IRQn);
+ systick_val = SysTick->VAL & SysTick_VAL_CURRENT_Msk;
+ NVIC_EnableIRQ(SysTick_IRQn);
+
+ return cpu_cycle_count + (SysTick->LOAD - systick_val);
+}
+
+
+/**
+ * SysTick initialisation
+ */
+static int Init_SysTick(void)
+{
+ const uint32_t ticks_10ms = get_mps4_core_clock()/100 + 1;
+ int err = 0;
+
+ /* Reset CPU cycle count value. */
+ cpu_cycle_count = 0;
+
+ /* Changing configuration for sys tick => guard from being
+ * interrupted. */
+ NVIC_DisableIRQ(SysTick_IRQn);
+
+ /* SysTick init - this will enable interrupt too. */
+ err = SysTick_Config(ticks_10ms);
+
+ /* Enable interrupt again. */
+ NVIC_EnableIRQ(SysTick_IRQn);
+
+ /* Wait for SysTick to kick off */
+ while (!err && !SysTick->VAL) {
+ __NOP();
+ }
+
+ return err;
+}
+
+static bool add_pmu_counter(uint64_t value,
+ const char* name,
+ const char* unit,
+ pmu_counters* counters)
+{
+ const uint32_t idx = counters->num_counters;
+ if (idx < NUM_PMU_COUNTERS) {
+ counters->counters[idx].value = value;
+ counters->counters[idx].name = name;
+ counters->counters[idx].unit = unit;
+ ++counters->num_counters;
+
+ debug("%s: %" PRIu64 " %s\n", name, value, unit);
+ return true;
+ }
+ printf_err("Failed to add PMU counter!\n");
+ return false;
+}
+
+static uint32_t get_tstamp_milliseconds(mps4_pmu_counters* mps4_counters)
+{
+ const uint32_t divisor = get_mps4_core_clock() / 1000;
+ if (mps4_counters->counter_100Hz > 100) {
+ return (mps4_counters->counter_100Hz * 10);
+ }
+ return (mps4_counters->counter_systick/divisor);
+}