Add Corstone-310 target

Change-Id: Idcb2238895668ee4858c2e858c02c6765f4b1702
diff --git a/applications/freertos/CMakeLists.txt b/applications/freertos/CMakeLists.txt
index 610f0e5..7bbfd97 100644
--- a/applications/freertos/CMakeLists.txt
+++ b/applications/freertos/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021 Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022 Arm Limited.
 #
 # SPDX-License-Identifier: Apache-2.0
 #
@@ -29,6 +29,7 @@
 
 # Use the fast memory to support both 11.12.57 and 11.13.x release
 # of the FVP
-# The size is defined to force the .bss.tensor_arena to be placed in DDR
-target_compile_definitions(
-    freertos PRIVATE ETHOSU_FAST_MEMORY_SIZE=0xa0000)
+target_compile_options(freertos PRIVATE
+    -UETHOSU_FAST_MEMORY_SIZE -DETHOSU_FAST_MEMORY_SIZE=0xa0000
+    -UETHOSU_ARENA -DETHOSU_ARENA=1
+    -UETHOSU_MODEL -DETHOSU_MODEL=1)
diff --git a/applications/threadx_demo/CMakeLists.txt b/applications/threadx_demo/CMakeLists.txt
index dbc56d2..c18d739 100644
--- a/applications/threadx_demo/CMakeLists.txt
+++ b/applications/threadx_demo/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021 Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022 Arm Limited.
 #
 # SPDX-License-Identifier: Apache-2.0
 #
@@ -31,5 +31,7 @@
 # Use the fast memory to support both 11.12.57 and 11.13.x release
 # of the FVP
 # The size is defined to force the .bss.tensor_arena to be placed in DDR
-target_compile_definitions(
-    threadx_demo PRIVATE ETHOSU_FAST_MEMORY_SIZE=0xa0000)
+target_compile_options(threadx_demo PRIVATE
+    -UETHOSU_FAST_MEMORY_SIZE -DETHOSU_FAST_MEMORY_SIZE=0xa0000
+    -UETHOSU_ARENA -DETHOSU_ARENA=1
+    -UETHOSU_MODEL -DETHOSU_MODEL=1)
diff --git a/applications/trustzone_inference/secure/CMakeLists.txt b/applications/trustzone_inference/secure/CMakeLists.txt
index 1e4a98b..b1f84f3 100644
--- a/applications/trustzone_inference/secure/CMakeLists.txt
+++ b/applications/trustzone_inference/secure/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021 Arm Limited. All rights reserved.
+# Copyright (c) 2021-2022 Arm Limited.
 #
 # SPDX-License-Identifier: Apache-2.0
 #
@@ -38,8 +38,10 @@
 
 # Use the fast memory to support both 11.12.57 and 11.13.x release
 # of the FVP
-target_compile_definitions(
-    trustzone_secure PUBLIC ETHOSU_FAST_MEMORY_SIZE=0xa0000)
+target_compile_options(trustzone_secure PUBLIC
+    -UETHOSU_FAST_MEMORY_SIZE -DETHOSU_FAST_MEMORY_SIZE=0xa0000
+    -UETHOSU_ARENA -DETHOSU_ARENA=1
+    -UETHOSU_MODEL -DETHOSU_MODEL=1)
 
 target_compile_options(trustzone_secure PUBLIC -mcmse)
 
diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake
index c12f427..8e0a8c3 100644
--- a/cmake/helpers.cmake
+++ b/cmake/helpers.cmake
@@ -40,6 +40,7 @@
     get_property(LINK_FILE GLOBAL PROPERTY ETHOSU_TARGET_LINK_FILE)
 
     set(prop "$<TARGET_PROPERTY:${target},COMPILE_DEFINITIONS>")
+    set(opt "$<TARGET_PROPERTY:${target},COMPILE_OPTIONS>")
 
     if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang")
         set(LINK_FILE_EXT scatter)
@@ -66,6 +67,7 @@
         DEPENDS ${LINK_FILE_IN}
         COMMAND ${CMAKE_C_COMPILER} ${COMPILER_PREPROCESSOR_OPTIONS} -o ${LINK_FILE_OUT} ${LINK_FILE_IN}
         COMMAND_EXPAND_LISTS "-D$<JOIN:${prop},;-D>"
+        COMMAND_EXPAND_LISTS "$<FILTER:${opt},INCLUDE,^(-U|-D)>"
         COMMAND_EXPAND_LISTS "-I$<JOIN:$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>,;-I>"
         COMMENT "Preprocessing and generating linker script"
         VERBATIM)
diff --git a/scripts/run_ctest.py b/scripts/run_ctest.py
index 93a5427..c2ba672 100755
--- a/scripts/run_ctest.py
+++ b/scripts/run_ctest.py
@@ -114,6 +114,31 @@
 
     return run_fvp(cmd)
 
+def run_corstone_310(args):
+    # Verify supported FVP version
+    version = subprocess.check_output(['FVP_Corstone_SSE-310', '--version']).decode()
+    supported_version = ['11.17']
+
+    if not [s for s in supported_version if s in version]:
+        raise Exception("Incorrect FVP version. Supported versions are '{}'.".format(supported_version))
+
+    # FVP executable
+    cmd = ['FVP_Corstone_SSE-310']
+
+    # NPU configuration
+    cmd += ['-C', 'ethosu.num_macs=' + str(args.macs)]
+
+    # Output parameters
+    cmd += ['-C', 'mps3_board.visualisation.disable-visualisation=1',
+            '-C', 'mps3_board.telnetterminal0.start_telnet=0',
+            '-C', 'mps3_board.uart0.out_file="-"',
+            '-C', 'mps3_board.uart0.unbuffered_output=1',
+            '-C', 'mps3_board.uart0.shutdown_on_eot=1']
+
+    cmd += args.args
+
+    return run_fvp(cmd)
+
 def run_corstone_polaris(args):
     # Verify supported FVP version
     version = subprocess.check_output(['FVP_Corstone-Polaris', '--version']).decode()
@@ -147,7 +172,7 @@
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(description='Run a test with given test command and test binary.')
-    parser.add_argument('-t', '--target', choices=['corstone-300', 'corstone-polaris'], required=True, help='FVP target.')
+    parser.add_argument('-t', '--target', choices=['corstone-300', 'corstone-310', 'corstone-polaris'], required=True, help='FVP target.')
     parser.add_argument('-a', '--arch', choices=['ethos-u55', 'ethos-u65'], help='NPU architecture.')
     parser.add_argument('-m', '--macs', type=int, choices=[32, 64, 128, 256, 512], default=128, help='NPU number of MACs.')
     parser.add_argument('-c', '--tarmac', dest='tarmac', action='store_true', help='Collect tarmac traces when running FVP.')
@@ -157,5 +182,7 @@
 
     if args.target == 'corstone-300':
         sys.exit(run_corstone_300(args))
+    elif args.target == 'corstone-310':
+        sys.exit(run_corstone_310(args))
     elif args.target == 'corstone-polaris':
         sys.exit(run_corstone_polaris(args))
diff --git a/targets/corstone-310/CMakeLists.txt b/targets/corstone-310/CMakeLists.txt
new file mode 100644
index 0000000..446a424
--- /dev/null
+++ b/targets/corstone-310/CMakeLists.txt
@@ -0,0 +1,144 @@
+#
+# Copyright (c) 2020-2022 Arm Limited. All rights reserved.
+#
+# 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
+#
+# 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.
+#
+
+#############################################################################
+# Default parameters
+#############################################################################
+
+# TODO Olympus CPU is backwards compatible with Cortex-M55
+set(TARGET_CPU "cortex-m55" CACHE INTERNAL "")
+
+if (NOT CMAKE_TOOLCHAIN_FILE)
+    set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/toolchain/armclang.cmake")
+endif()
+
+set(ETHOSU_TARGET_NPU_CONFIG "ethos-u55-128" CACHE STRING "NPU configuration")
+set(ETHOSU_TARGET_NPU_COUNT 1 CACHE INTERNAL "Number of NPUs")
+set(ETHOSU_TARGET_NPU_TA_COUNT 2 CACHE INTERNAL "Number of timing adapters per NPU")
+
+set(ETHOSU_PMU_EVENT_0 -1 CACHE STRING "PMU Event #0")
+set(ETHOSU_PMU_EVENT_1 -1 CACHE STRING "PMU Event #1")
+set(ETHOSU_PMU_EVENT_2 -1 CACHE STRING "PMU Event #2")
+set(ETHOSU_PMU_EVENT_3 -1 CACHE STRING "PMU Event #3")
+
+set(FAST_MEMORY_SIZE 0 CACHE STRING "Size of relocated fast memory scratch tensor")
+
+if (${FAST_MEMORY_SIZE} EQUAL 0)
+    set(MEMORY_DEFAULT "sram")
+else()
+    set(MEMORY_DEFAULT "dram")
+endif()
+
+set(MEMORY_MODEL ${MEMORY_DEFAULT} CACHE STRING "Memory config for model")
+set(MEMORY_ARENA ${MEMORY_DEFAULT} CACHE STRING "Memory config for arena")
+
+set(SYSTEM_CORE_CLOCK "25000000" CACHE INTERNAL "System core clock (Hz)")
+
+#############################################################################
+# Project
+#############################################################################
+
+cmake_minimum_required(VERSION 3.21)
+
+project(ethos-u-corstone-polaris VERSION 0.0.1)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/helpers.cmake)
+
+#############################################################################
+# Corstone-Polaris
+#############################################################################
+
+get_filename_component(ETHOSU_TARGET ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+message("Configuring target ${ETHOSU_TARGET}")
+
+# Enable CTest
+include(CTest)
+set(Python3_FIND_STRATEGY LOCATION)
+find_package(Python3 COMPONENTS Interpreter)
+ethosu_get_architecture(${ETHOSU_TARGET_NPU_CONFIG})
+set(ETHOSU_COMMAND_DEFAULT ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/run_ctest.py
+        -t corstone-310
+        -a ethos-${ETHOSU_ARCH}
+        -m ${ETHOSU_NUM_MACS}
+    CACHE INTERNAL "Default test command")
+
+# Enable trustzone support in core_software
+set(TRUSTZONE_BUILD OFF)
+
+# Include common targets
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../common target)
+
+target_compile_definitions(ethosu_target_common INTERFACE
+    # Confiugure NPU architecture and number of timing adapters
+    ETHOSU_NPU_COUNT=${ETHOSU_TARGET_NPU_COUNT}
+    ETHOSU_NPU_TA_COUNT=${ETHOSU_TARGET_NPU_TA_COUNT}
+
+    # Configure PMU events
+    ETHOSU_PMU_EVENT_0=${ETHOSU_PMU_EVENT_0}
+    ETHOSU_PMU_EVENT_1=${ETHOSU_PMU_EVENT_1}
+    ETHOSU_PMU_EVENT_2=${ETHOSU_PMU_EVENT_2}
+    ETHOSU_PMU_EVENT_3=${ETHOSU_PMU_EVENT_3}
+
+    # Placement or TLFu model and area. 0 = SRAM, 1 = DRAM
+    ETHOSU_FAST_MEMORY_SIZE=${FAST_MEMORY_SIZE}
+    ETHOSU_MODEL=$<STREQUAL:${MEMORY_MODEL},dram>
+    ETHOSU_ARENA=$<STREQUAL:${MEMORY_ARENA},dram>)
+
+# AXI Timing adaptors
+set(registers MAXR MAXW MAXRW RLATENCY WLATENCY PULSE_ON PULSE_OFF BWCAP PERFCTRL PERFCNT MODE HISTBIN HISTCNT)
+
+foreach(register ${registers})
+    foreach(index RANGE 0 1)
+        set(name ETHOSU_TA_${register}_${index})
+        set(${name} -1 CACHE STRING "${name}")
+
+        if (${name} GREATER_EQUAL 0)
+            target_compile_definitions(ethosu_target_common INTERFACE ${name}=${${name}})
+        endif()
+    endforeach()
+endforeach()
+
+# Linker script
+set(LINK_FILE platform CACHE STRING "Link file")
+
+ethosu_target_link_options(ethosu_target_link INTERFACE
+    LINK_FILE ${LINK_FILE}
+    ENTRY Reset_Handler)
+
+# Add drivers
+target_sources(ethosu_target_startup INTERFACE
+    retarget.c
+    target.cpp)
+
+target_link_libraries(ethosu_target_startup INTERFACE
+    $<$<TARGET_EXISTS:ethosu_core_driver>:ethosu_core_driver;timing_adapter>
+    mpu
+    ethosu_mhu_dummy
+    ethosu_uart_cmsdk_apb)
+
+if (TARGET ethosu_core_driver)
+    target_compile_definitions(ethosu_core_driver PUBLIC
+        ETHOSU)
+endif()
+
+###############################################################################
+# Applications
+###############################################################################
+
+# Add all applications
+add_subdirectory(../../applications applications)
diff --git a/targets/corstone-310/platform.ld b/targets/corstone-310/platform.ld
new file mode 100644
index 0000000..21c46b9
--- /dev/null
+++ b/targets/corstone-310/platform.ld
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2009-2022 Arm Limited. All rights reserved.
+ *
+ * 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
+ *
+ * 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.
+ */
+
+/*
+ * Corstone-310 is the next generation Corstone-300 where the CPU
+ * has been upgraded to Cortex-M85.
+ *
+ * This is a simplified picture of the Corstone-310 memory system.
+ * Please refer to the Corstone SSE-310 Technical Reference Manual for
+ * further information.
+ *
+ * https://developer.arm.com/ip-products/subsystem/corstone/corstone-300
+ *
+ * +---------------+   +---------------+  +------+
+ * | Ethos-U55     |   | Cortex-M85    +--+ ITCM |
+ * |               |   |               |  +------+
+ * |               |   |               |
+ * |               |   |               |  +------+
+ * |  M1      M0   |   |               +--+ DTCM |
+ * +---+-------+---+   +-------+-------+  +------+
+ *     |       |               |
+ *     |   +---+---------------+-----+
+ *     |   | AMBA AXI NIC-400-Lite   |
+ *     |   +---+-----------------+---+
+ *     |       |                 |
+ * +---+-------+------------+ +--+-------+
+ * | AMBA AXI NIC-400       | | SSE-300  |
+ * +---+--------+--------+--+ | SRAM     |
+ *     |        |        |    +----------+
+ * +---+---+ +--+---+ +--+--+
+ * | Flash | | BRAM | | DDR |
+ * +-------+ +------+ +-----+
+ *
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ * |  Memory region name   | Base addr   |    Size     |IDAU|  MCC load address + remarks          |
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ * | ITCM                  | 0x0000_0000 | 0x0000_8000 | NS | 32 kiB                               |
+ * | ITCM                  | 0x1000_0000 | 0x0000_8000 | S  | Secure alias for NS ITCM             |
+ * | FPGA Data SRAM; BRAM  | 0x0100_0000 | 0x0020_0000 | NS | 2 MiB                                |
+ * | FPGA data SRAM; BRAM  | 0x1100_0000 | 0x0020_0000 | S  | Secure alias for NS BRAM             |
+ * | DTCM                  | 0x2000_0000 | 0x0000_8000 | NS | 32 kiB                               |
+ * | DTCM                  | 0x3000_0000 | 0x0000_8000 | S  | Secure alias for NS DTCM             |
+ * | SSE-300 internal SRAM | 0x2100_0000 | 0x0040_0000 | NS | 2 banks of 2 MiB; 3 cycles latency   |
+ * | SSE-300 internal SRAM | 0x3100_0000 | 0x0040_0000 | S  | Secure alias for NS internal SRAM    |
+ * | DDR                   | 0x6000_0000 | 0x1000_0000 | NS | 256 MB bank                          |
+ * | DDR                   | 0x7000_0000 | 0x1000_0000 | S  | Secure alias for NS DDR              |
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ *
+ *  Note: Ethos-U55 can access BRAM, internal SRAM and the DDR sections => activation buffers and
+ *        the model should only be placed in those regions.
+ *
+ *  Note: Alias regions means that secure and non-secure addresses are mapped to the same physical
+ *        memory banks.
+ */
+
+/* default value - '1', for DRAM */
+#ifndef ETHOSU_MODEL
+#define ETHOSU_MODEL  1
+#endif
+
+/* default value - '1', for DRAM */
+#ifndef ETHOSU_ARENA
+#define ETHOSU_ARENA  1
+#endif
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 0x8000
+#endif
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 0x10000
+#endif
+
+__STACK_SIZE = STACK_SIZE;
+__HEAP_SIZE  = HEAP_SIZE;
+
+MEMORY
+{
+  ITCM  (rx)  : ORIGIN = 0x10000000, LENGTH = 0x00008000
+  BRAM  (rw)  : ORIGIN = 0x11000000, LENGTH = 0x00200000
+  DTCM  (rw)  : ORIGIN = 0x30000000, LENGTH = 0x00008000
+  SRAM  (rw)  : ORIGIN = 0x31000000, LENGTH = 0x00400000
+  QSPI  (rw)  : ORIGIN = 0x38000000, LENGTH = 0x00800000
+  DDR   (rwx) : ORIGIN = 0x70000000, LENGTH = 0x10000000
+}
+
+PHDRS
+{
+    rom_exec PT_LOAD;
+    rom_dram PT_LOAD;
+    null     PT_NULL;
+}
+
+/* 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 :
+  {
+    KEEP(*(.vectors))
+    *crt* (.text*)
+    *startup_ARMCM55.c.obj (.text*)
+    *system_ARMCM55.c.obj (.text*)
+    *target.cpp.obj (.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)
+
+    *(.text*)
+
+    KEEP(*(.eh_frame*))
+  } > BRAM :rom_exec
+
+  .data :
+  {
+    . = ALIGN(4);
+    __data_start__ = .;
+
+    *(vtable)
+    *(.data)
+    *(.data.*)
+    *(.rodata*)
+
+    . = ALIGN(4);
+    __data_end__ = .;
+  } > BRAM :rom_exec
+
+  /*
+   * SG veneers:
+   * All SG veneers are placed in the special output section .gnu.sgstubs. Its start address
+   * must be set, either with the command line option '--section-start' or in a linker script,
+   * to indicate where to place these veneers in memory.
+   */
+/*
+  .gnu.sgstubs :
+  {
+    . = ALIGN(32);
+  } > BRAM :rom_exec
+*/
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > BRAM :rom_exec
+
+  .ARM.exidx :
+  {
+  __exidx_start = .;
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  __exidx_end = .;
+  } > BRAM :rom_exec
+
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+
+    LONG (LOADADDR(.sram))
+    LONG (ADDR(.sram))
+    LONG (SIZEOF(.sram))
+
+    __copy_table_end__ = .;
+  } > BRAM :rom_exec
+
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+
+    LONG (ADDR(.bss))
+    LONG (SIZEOF(.bss))
+
+    LONG (ADDR(.sram.bss))
+    LONG (SIZEOF(.sram.bss))
+
+    __zero_table_end__ = .;
+  } > BRAM :rom_exec
+
+  .sram : AT(__etext)
+  {
+#if (ETHOSU_MODEL == 0)
+    . = ALIGN(16);
+    *(network_model_sec)
+#endif
+
+    . = ALIGN(16);
+    *(.sram.data)
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__init_array_end = .);
+
+    . = ALIGN(4);
+    /* finit data */
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP(*(SORT(.fini_array.*)))
+    KEEP(*(.fini_array))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+
+    KEEP(*(.jcr*))
+  } > SRAM :rom_dram
+
+  .sram.bss :
+  {
+#if (ETHOSU_ARENA == 0)
+    . = ALIGN(16);
+    *(.bss.tensor_arena)
+#endif
+
+    . = ALIGN(16);
+    *(.bss.ethosu_scratch);
+  } > SRAM :null
+
+  .ddr :
+  {
+#if (ETHOSU_ARENA == 1)
+    . = ALIGN(16);
+    *(.bss.tensor_arena)
+#endif
+
+#if (ETHOSU_MODEL == 1)
+    . = ALIGN(16);
+    *(network_model_sec)
+#endif
+
+    . = ALIGN(4);
+    *(input_data_sec)
+    *(expected_output_data_sec)
+    *(output_data_sec)
+
+    *(ethosu_core_in_queue ethosu_core_out_queue)
+
+    /* Place data for scatter loading here */
+    __etext = .;
+  } > DDR :rom_dram
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > BRAM :null
+
+  .heap (COPY) :
+  {
+    . = ALIGN(8);
+    __end__ = .;
+    PROVIDE(end = .);
+    . = . + __HEAP_SIZE;
+    . = ALIGN(8);
+    __HeapLimit = .;
+  } > BRAM :null
+
+  .stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) :
+  {
+    . = ALIGN(8);
+    __StackLimit = .;
+    . = . + __STACK_SIZE;
+    . = ALIGN(8);
+    __StackTop = .;
+  } > DTCM :null
+  PROVIDE(__stack = __StackTop);
+
+  /* Check if data + heap + stack exceeds DTCM limit */
+  ASSERT(LENGTH(DTCM) >= __STACK_SIZE, "region DTCM overflowed with stack")
+}
diff --git a/targets/corstone-310/platform.scatter b/targets/corstone-310/platform.scatter
new file mode 100644
index 0000000..f23f3a3
--- /dev/null
+++ b/targets/corstone-310/platform.scatter
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2019-2022 Arm Limited. All rights reserved.
+ *
+ * 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
+ *
+ * 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.
+ */
+
+/*
+ * Corstone-310 is the next generation Corstone-300 where the CPU
+ * has been upgraded to Cortex-M85.
+ *
+ * This is a simplified picture of the Corstone-310 memory system.
+ * Please refer to the Corstone SSE-310 Technical Reference Manual for
+ * further information.
+ *
+ * https://developer.arm.com/ip-products/subsystem/corstone/corstone-300
+ *
+ * +---------------+   +---------------+  +------+
+ * | Ethos-U55     |   | Cortex-M85    +--+ ITCM |
+ * |               |   |               |  +------+
+ * |               |   |               |
+ * |               |   |               |  +------+
+ * |  M1      M0   |   |               +--+ DTCM |
+ * +---+-------+---+   +-------+-------+  +------+
+ *     |       |               |
+ *     |   +---+---------------+-----+
+ *     |   | AMBA AXI NIC-400-Lite   |
+ *     |   +---+-----------------+---+
+ *     |       |                 |
+ * +---+-------+------------+ +--+-------+
+ * | AMBA AXI NIC-400       | | SSE-300  |
+ * +---+--------+--------+--+ | SRAM     |
+ *     |        |        |    +----------+
+ * +---+---+ +--+---+ +--+--+
+ * | Flash | | BRAM | | DDR |
+ * +-------+ +------+ +-----+
+ *
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ * |  Memory region name   | Base addr   |    Size     |IDAU|  MCC load address + remarks          |
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ * | ITCM                  | 0x0000_0000 | 0x0000_8000 | NS | 32 kiB                               |
+ * | ITCM                  | 0x1000_0000 | 0x0000_8000 | S  | Secure alias for NS ITCM             |
+ * | FPGA Data SRAM; BRAM  | 0x0100_0000 | 0x0020_0000 | NS | 2 MiB                                |
+ * | FPGA data SRAM; BRAM  | 0x1100_0000 | 0x0020_0000 | S  | Secure alias for NS BRAM             |
+ * | DTCM                  | 0x2000_0000 | 0x0000_8000 | NS | 32 kiB                               |
+ * | DTCM                  | 0x3000_0000 | 0x0000_8000 | S  | Secure alias for NS DTCM             |
+ * | SSE-300 internal SRAM | 0x2100_0000 | 0x0040_0000 | NS | 2 banks of 2 MiB; 3 cycles latency   |
+ * | SSE-300 internal SRAM | 0x3100_0000 | 0x0040_0000 | S  | Secure alias for NS internal SRAM    |
+ * | DDR                   | 0x6000_0000 | 0x1000_0000 | NS | 256 MB bank                          |
+ * | DDR                   | 0x7000_0000 | 0x1000_0000 | S  | Secure alias for NS DDR              |
+ * +-----------------------+-------------+-------------+----+--------------------------------------+
+ *
+ *  Note: Ethos-U55 can access BRAM, internal SRAM and the DDR sections => activation buffers and
+ *        the model should only be placed in those regions.
+ *
+ *  Note: Alias regions means that secure and non-secure addresses are mapped to the same physical
+ *        memory banks.
+ */
+
+/* default value - '1', for DRAM */
+#ifndef ETHOSU_MODEL
+#define ETHOSU_MODEL  1
+#endif
+
+/* default value - '1', for DRAM */
+#ifndef ETHOSU_ARENA
+#define ETHOSU_ARENA  1
+#endif
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 0x8000
+#endif
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 0x10000
+#endif
+
+#define ITCM_START 0x10000000
+#define ITCM_SIZE  0x00008000
+
+#define DTCM_START 0x30000000
+#define DTCM_SIZE  0x00008000
+
+#define BRAM_START 0x11000000
+#define BRAM_SIZE  0x00200000
+
+#define SRAM_START 0x31000000
+#define SRAM_SIZE  0x00400000
+
+#define DDR_START  0x70000000
+#define DDR_SIZE   0x10000000
+
+#if STACK_SIZE > DTCM_SIZE
+#error Stack size larger than DTCM size
+#endif
+
+/* ----------------------------------------------------------------------------
+  Stack seal size definition
+ *----------------------------------------------------------------------------*/
+
+APP_IMAGE BRAM_START BRAM_SIZE
+{
+    rom_exec BRAM_START BRAM_SIZE
+    {
+        *.o (RESET, +First)
+        *(InRoot$$Sections)
+        startup_ARMCM55.o
+        system_ARMCM55.o
+        target.o
+        .ANY1 (+RO +RW +ZI)
+    }
+
+    ARM_LIB_HEAP +0 EMPTY ALIGN 8 HEAP_SIZE {}
+    ARM_LIB_STACK DTCM_START EMPTY ALIGN 8 STACK_SIZE {}
+}
+
+; Place all SRAM and DDR execution regions in DDR. We have plenty of DDR
+; and can perform scatter loading from here.
+LOAD_REGION_DDR DDR_START DDR_SIZE
+{
+    ; Place model and its affiliates in DRAM
+    rom_dram DDR_START
+    {
+#if (ETHOSU_MODEL == 1)
+        * (network_model_sec)
+#endif
+        * (input_data_sec)
+        * (expected_output_data_sec)
+        * (output_data_sec)
+    }
+
+#if (ETHOSU_ARENA == 1)
+    ; Place tensor arena in DRAM if we have a fast memory area
+    ARENA +0 UNINIT ALIGN 16
+    {
+        * (.bss.tensor_arena)
+    }
+#endif
+
+    SRAM SRAM_START ALIGN 16 SRAM_SIZE
+    {
+#if (ETHOSU_MODEL == 0)
+        ; Place network model in SRAM
+        * (network_model_sec)
+#endif
+
+#if (ETHOSU_ARENA == 0)
+        ; Place tensor arena in SRAM
+        * (.bss.tensor_arena)
+#endif
+
+        ; Place scratch buffer in SRAM
+        * (.bss.ethosu_scratch)
+
+        ; SRAM data
+        * (.sram.data)
+    }
+}
diff --git a/targets/corstone-310/retarget.c b/targets/corstone-310/retarget.c
new file mode 100644
index 0000000..eb1c908
--- /dev/null
+++ b/targets/corstone-310/retarget.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2019-2022 Arm Limited. All rights reserved.
+ *
+ * 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
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "uart_stdout.h"
+
+// armclang retargeting
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
+#include <rt_misc.h>
+#include <rt_sys.h>
+
+/* Standard IO device handles. */
+#define STDIN  0x8001
+#define STDOUT 0x8002
+#define STDERR 0x8003
+
+#define RETARGET(fun)  _sys##fun
+#define IO_OUTPUT(len) 0
+
+#else
+/*
+ * This type is used by the _ I/O functions to denote an open
+ * file.
+ */
+typedef int FILEHANDLE;
+
+/*
+ * Open a file. May return -1 if the file failed to open.
+ */
+extern FILEHANDLE _open(const char * /*name*/, int /*openmode*/);
+
+/* Standard IO device handles. */
+#define STDIN  0x00
+#define STDOUT 0x01
+#define STDERR 0x02
+
+#define RETARGET(fun)  fun
+#define IO_OUTPUT(len) len
+
+#endif
+
+/* Standard IO device name defines. */
+const char __stdin_name[] __attribute__((aligned(4)))  = "STDIN";
+const char __stdout_name[] __attribute__((aligned(4))) = "STDOUT";
+const char __stderr_name[] __attribute__((aligned(4))) = "STDERR";
+
+void _ttywrch(int ch) {
+    (void)fputc(ch, stdout);
+}
+
+FILEHANDLE RETARGET(_open)(const char *name, int openmode) {
+    (void)openmode;
+
+    if (strcmp(name, __stdin_name) == 0) {
+        return (STDIN);
+    }
+
+    if (strcmp(name, __stdout_name) == 0) {
+        return (STDOUT);
+    }
+
+    if (strcmp(name, __stderr_name) == 0) {
+        return (STDERR);
+    }
+
+    return -1;
+}
+
+int RETARGET(_write)(FILEHANDLE fh, const unsigned char *buf, unsigned int len, int mode) {
+    (void)mode;
+
+    switch (fh) {
+    case STDOUT:
+    case STDERR: {
+        int c;
+        unsigned int i;
+
+        for (i = 0; i < len; i++) {
+            c = fputc(buf[i], stdout);
+            if (c == EOF) {
+                return EOF;
+            }
+        }
+
+        return IO_OUTPUT(len);
+    }
+    default:
+        return EOF;
+    }
+}
+
+int RETARGET(_read)(FILEHANDLE fh, unsigned char *buf, unsigned int len, int mode) {
+    (void)mode;
+
+    switch (fh) {
+    case STDIN: {
+        int c;
+        unsigned int i;
+
+        for (i = 0; i < len; i++) {
+            c = fgetc(stdin);
+            if (c == EOF) {
+                return EOF;
+            }
+
+            buf[i] = (unsigned char)c;
+        }
+
+        return IO_OUTPUT(len);
+    }
+    default:
+        return EOF;
+    }
+}
+
+int RETARGET(_istty)(FILEHANDLE fh) {
+    switch (fh) {
+    case STDIN:
+    case STDOUT:
+    case STDERR:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
+int RETARGET(_close)(FILEHANDLE fh) {
+    if (RETARGET(_istty(fh))) {
+        return 0;
+    }
+
+    return -1;
+}
+
+int RETARGET(_seek)(FILEHANDLE fh, long pos) {
+    (void)fh;
+    (void)pos;
+
+    return -1;
+}
+
+int RETARGET(_ensure)(FILEHANDLE fh) {
+    (void)fh;
+
+    return -1;
+}
+
+long RETARGET(_flen)(FILEHANDLE fh) {
+    if (RETARGET(_istty)(fh)) {
+        return 0;
+    }
+
+    return -1;
+}
+
+int RETARGET(_tmpnam)(char *name, int sig, unsigned maxlen) {
+    (void)name;
+    (void)sig;
+    (void)maxlen;
+
+    return 1;
+}
+
+char *RETARGET(_command_string)(char *cmd, int len) {
+    (void)len;
+
+    return cmd;
+}
+
+void RETARGET(_exit)(int return_code) {
+    char exit_code_buffer[64] = {0};
+    const char *p             = exit_code_buffer;
+
+    /* Print out the exit code on the uart so any reader know how we exit. */
+    /* By appending 0x04, ASCII for end-of-transmission the FVP model exits,
+     * if the configuration parameter shutdown_on_eot on the uart is enabled.
+     * For some versions of FVP, the shutdown_on_eot is broken, but the same
+     * behaviour can be created by passing specifying a shutdown_tag= for the
+     * uart when starting the model so that is added last as well.
+     */
+
+    snprintf(exit_code_buffer,
+             sizeof(exit_code_buffer),
+             "Application exit code: %d.\n" // Let the readers know how we exit
+             "\04\n"                        // end-of-transmission
+             "EXITTHESIM\n",                // shutdown_tag
+             return_code);
+
+    while (*p != '\0') {
+        UartPutc(*p++);
+    }
+
+    while (1) {}
+}
+
+int system(const char *cmd) {
+    (void)cmd;
+
+    return 0;
+}
+
+time_t time(time_t *timer) {
+    time_t current;
+
+    current = 0; // To Do !! No RTC implemented
+
+    if (timer != NULL) {
+        *timer = current;
+    }
+
+    return current;
+}
+
+void _clock_init(void) {
+#if 0
+    // Example implementation based on SysTick
+    // For instance, use a counting var in a SysTick interrupt handler
+    // for clock() to use
+    SysTick->LOAD = (uint32_t) ((SystemCoreClock/100)-1UL);
+    NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
+    SysTick->VAL = 0UL;
+    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
+#endif
+}
+
+clock_t clock(void) {
+    return (clock_t)-1;
+}
+
+int remove(const char *arg) {
+    (void)arg;
+    return 0;
+}
+
+int rename(const char *oldn, const char *newn) {
+    (void)oldn;
+    (void)newn;
+    return 0;
+}
+
+int fputc(int ch, FILE *f) {
+    (void)(f);
+    return UartPutc(ch);
+}
+
+int fgetc(FILE *f) {
+    (void)f;
+    return UartPutc(UartGetc());
+}
+
+#ifndef ferror
+/* arm-none-eabi-gcc with newlib uses a define for ferror */
+int ferror(FILE *f) {
+    (void)f;
+    return EOF;
+}
+#endif
diff --git a/targets/corstone-310/target.cpp b/targets/corstone-310/target.cpp
new file mode 100644
index 0000000..c979dbb
--- /dev/null
+++ b/targets/corstone-310/target.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2020-2022 Arm Limited. All rights reserved.
+ *
+ * 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
+ *
+ * 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.
+ */
+
+/****************************************************************************
+ * Includes
+ ****************************************************************************/
+
+#include "target.hpp"
+
+#ifdef ETHOSU
+#include <ethosu_driver.h>
+#include <timing_adapter.h>
+#endif
+
+#include "mpu.hpp"
+#include "uart_stdout.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+
+using namespace EthosU;
+
+/****************************************************************************
+ * Defines
+ ****************************************************************************/
+
+#define ETHOSU_BASE_ADDRESS 0x50004000
+#define ETHOSU_IRQ          16
+
+#define ETHOSU0_TA0_BASE_ADDRESS 0x58103000
+#define ETHOSU0_TA1_BASE_ADDRESS 0x58103200
+
+/****************************************************************************
+ * Variables
+ ****************************************************************************/
+
+#if defined(ETHOSU_FAST_MEMORY_SIZE) && ETHOSU_FAST_MEMORY_SIZE > 0
+__attribute__((aligned(16), section(".bss.ethosu_scratch"))) uint8_t ethosu_scratch[ETHOSU_FAST_MEMORY_SIZE];
+#else
+#define ethosu_scratch          0
+#define ETHOSU_FAST_MEMORY_SIZE 0
+#endif
+
+#ifdef ETHOSU
+struct ethosu_driver ethosu0_driver;
+#endif
+
+/****************************************************************************
+ * Timing Adapters
+ ****************************************************************************/
+
+#ifdef ETHOSU
+
+#ifndef ETHOSU_TA_MAXR_0
+#define ETHOSU_TA_MAXR_0 0
+#endif
+
+#ifndef ETHOSU_TA_MAXW_0
+#define ETHOSU_TA_MAXW_0 0
+#endif
+
+#ifndef ETHOSU_TA_MAXRW_0
+#define ETHOSU_TA_MAXRW_0 0
+#endif
+
+#ifndef ETHOSU_TA_RLATENCY_0
+#define ETHOSU_TA_RLATENCY_0 0
+#endif
+
+#ifndef ETHOSU_TA_WLATENCY_0
+#define ETHOSU_TA_WLATENCY_0 0
+#endif
+
+#ifndef ETHOSU_TA_PULSE_ON_0
+#define ETHOSU_TA_PULSE_ON_0 0
+#endif
+
+#ifndef ETHOSU_TA_PULSE_OFF_0
+#define ETHOSU_TA_PULSE_OFF_0 0
+#endif
+
+#ifndef ETHOSU_TA_BWCAP_0
+#define ETHOSU_TA_BWCAP_0 0
+#endif
+
+#ifndef ETHOSU_TA_PERFCTRL_0
+#define ETHOSU_TA_PERFCTRL_0 0
+#endif
+
+#ifndef ETHOSU_TA_PERFCNT_0
+#define ETHOSU_TA_PERFCNT_0 0
+#endif
+
+#ifndef ETHOSU_TA_MODE_0
+#define ETHOSU_TA_MODE_0 1
+#endif
+
+#ifndef ETHOSU_TA_HISTBIN_0
+#define ETHOSU_TA_HISTBIN_0 0
+#endif
+
+#ifndef ETHOSU_TA_HISTCNT_0
+#define ETHOSU_TA_HISTCNT_0 0
+#endif
+
+#ifndef ETHOSU_TA_MAXR_1
+#define ETHOSU_TA_MAXR_1 0
+#endif
+
+#ifndef ETHOSU_TA_MAXW_1
+#define ETHOSU_TA_MAXW_1 0
+#endif
+
+#ifndef ETHOSU_TA_MAXRW_1
+#define ETHOSU_TA_MAXRW_1 0
+#endif
+
+#ifndef ETHOSU_TA_RLATENCY_1
+#define ETHOSU_TA_RLATENCY_1 0
+#endif
+
+#ifndef ETHOSU_TA_WLATENCY_1
+#define ETHOSU_TA_WLATENCY_1 0
+#endif
+
+#ifndef ETHOSU_TA_PULSE_ON_1
+#define ETHOSU_TA_PULSE_ON_1 0
+#endif
+
+#ifndef ETHOSU_TA_PULSE_OFF_1
+#define ETHOSU_TA_PULSE_OFF_1 0
+#endif
+
+#ifndef ETHOSU_TA_BWCAP_1
+#define ETHOSU_TA_BWCAP_1 0
+#endif
+
+#ifndef ETHOSU_TA_PERFCTRL_1
+#define ETHOSU_TA_PERFCTRL_1 0
+#endif
+
+#ifndef ETHOSU_TA_PERFCNT_1
+#define ETHOSU_TA_PERFCNT_1 0
+#endif
+
+#ifndef ETHOSU_TA_MODE_1
+#define ETHOSU_TA_MODE_1 1
+#endif
+
+#ifndef ETHOSU_TA_HISTBIN_1
+#define ETHOSU_TA_HISTBIN_1 0
+#endif
+
+#ifndef ETHOSU_TA_HISTCNT_1
+#define ETHOSU_TA_HISTCNT_1 0
+#endif
+
+static uintptr_t ethosu_ta_base_addrs[ETHOSU_NPU_COUNT][ETHOSU_NPU_TA_COUNT] = {
+    {ETHOSU0_TA0_BASE_ADDRESS, ETHOSU0_TA1_BASE_ADDRESS}};
+struct timing_adapter ethosu_ta[ETHOSU_NPU_COUNT][ETHOSU_NPU_TA_COUNT];
+struct timing_adapter_settings ethosu_ta_settings[ETHOSU_NPU_TA_COUNT] = {{ETHOSU_TA_MAXR_0,
+                                                                           ETHOSU_TA_MAXW_0,
+                                                                           ETHOSU_TA_MAXRW_0,
+                                                                           ETHOSU_TA_RLATENCY_0,
+                                                                           ETHOSU_TA_WLATENCY_0,
+                                                                           ETHOSU_TA_PULSE_ON_0,
+                                                                           ETHOSU_TA_PULSE_OFF_0,
+                                                                           ETHOSU_TA_BWCAP_0,
+                                                                           ETHOSU_TA_PERFCTRL_0,
+                                                                           ETHOSU_TA_PERFCNT_0,
+                                                                           ETHOSU_TA_MODE_0,
+                                                                           0, // Read only register
+                                                                           ETHOSU_TA_HISTBIN_0,
+                                                                           ETHOSU_TA_HISTCNT_0},
+                                                                          {ETHOSU_TA_MAXR_1,
+                                                                           ETHOSU_TA_MAXW_1,
+                                                                           ETHOSU_TA_MAXRW_1,
+                                                                           ETHOSU_TA_RLATENCY_1,
+                                                                           ETHOSU_TA_WLATENCY_1,
+                                                                           ETHOSU_TA_PULSE_ON_1,
+                                                                           ETHOSU_TA_PULSE_OFF_1,
+                                                                           ETHOSU_TA_BWCAP_1,
+                                                                           ETHOSU_TA_PERFCTRL_1,
+                                                                           ETHOSU_TA_PERFCNT_1,
+                                                                           ETHOSU_TA_MODE_1,
+                                                                           0, // Read only register
+                                                                           ETHOSU_TA_HISTBIN_1,
+                                                                           ETHOSU_TA_HISTCNT_1}};
+
+#endif
+
+/****************************************************************************
+ * Cache maintenance
+ ****************************************************************************/
+
+#if defined(CPU_CACHE_ENABLE) && defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+extern "C" {
+void ethosu_flush_dcache(uint32_t *p, size_t bytes) {
+    if (p)
+        SCB_CleanDCache_by_Addr(p, bytes);
+    else
+        SCB_CleanDCache();
+}
+
+void ethosu_invalidate_dcache(uint32_t *p, size_t bytes) {
+    if (p)
+        SCB_InvalidateDCache_by_Addr(p, bytes);
+    else
+        SCB_InvalidateDCache();
+}
+}
+#endif
+
+/****************************************************************************
+ * Init
+ ****************************************************************************/
+
+namespace {
+
+extern "C" {
+struct ExcContext {
+    uint32_t r0;
+    uint32_t r1;
+    uint32_t r2;
+    uint32_t r3;
+    uint32_t r12;
+    uint32_t lr;
+    uint32_t pc;
+    uint32_t xPsr;
+};
+
+void HardFault_Handler() {
+    int irq;
+    struct ExcContext *e;
+    uint32_t sp;
+
+    asm volatile("mrs %0, ipsr            \n" // Read IPSR (Exceptio number)
+                 "sub %0, #16             \n" // Get it into IRQn_Type range
+                 "tst lr, #4              \n" // Select the stack which was in use
+                 "ite eq                  \n"
+                 "mrseq %1, msp           \n"
+                 "mrsne %1, psp           \n"
+                 "mov %2, sp              \n"
+                 : "=r"(irq), "=r"(e), "=r"(sp));
+
+    printf("Hard fault. irq=%d, pc=0x%08" PRIx32 ", lr=0x%08" PRIx32 ", xpsr=0x%08" PRIx32 ", sp=0x%08" PRIx32 "\n",
+           irq,
+           e->pc,
+           e->lr,
+           e->xPsr,
+           sp);
+    printf(
+        "%11s cfsr=0x%08" PRIx32 " bfar=0x%08" PRIx32 " mmfar=0x%08" PRIx32 "\n", "", SCB->CFSR, SCB->BFAR, SCB->MMFAR);
+    exit(1);
+}
+}
+
+#ifdef ETHOSU
+void ethosuIrqHandler() {
+    ethosu_irq_handler(&ethosu0_driver);
+}
+#endif
+
+} // namespace
+
+namespace EthosU {
+
+void targetSetup() {
+    // Initialize UART driver
+    UartStdOutInit();
+
+#ifdef ETHOSU
+    // Initialize timing adapter(s)
+    for (int i = 0; i < ETHOSU_NPU_COUNT; i++) {
+        for (int j = 0; j < ETHOSU_NPU_TA_COUNT; j++) {
+            if (ta_init(&ethosu_ta[i][j], ethosu_ta_base_addrs[i][j])) {
+                printf("Failed to initialize timing-adapter %d for NPU %d\n", j, i);
+            } else {
+                // Set the updated configuration
+                ta_set_all(&ethosu_ta[i][j], &ethosu_ta_settings[j]);
+            }
+        }
+    }
+
+    // Initialize Ethos-U NPU driver
+    if (ethosu_init(&ethosu0_driver,
+                    reinterpret_cast<void *>(ETHOSU_BASE_ADDRESS),
+                    ethosu_scratch,
+                    ETHOSU_FAST_MEMORY_SIZE,
+                    1,
+                    1)) {
+        printf("Failed to initialize NPU.\n");
+        return;
+    }
+
+    // Assumes SCB->VTOR point to RW memory
+    NVIC_SetVector(static_cast<IRQn_Type>(ETHOSU_IRQ), (uint32_t)&ethosuIrqHandler);
+    NVIC_EnableIRQ(static_cast<IRQn_Type>(ETHOSU_IRQ));
+#endif
+
+    // MPU setup
+    const std::vector<ARM_MPU_Region_t> mpuConfig = {
+        {
+            // ITCM (NS)
+            ARM_MPU_RBAR(0x00000000,      // Base
+                         ARM_MPU_SH_NON,  // Non-shareable
+                         1,               // Read-Only
+                         1,               // Non-Privileged
+                         0),              // eXecute Never disabled
+            ARM_MPU_RLAR(0x00007fff,      // Limit
+                         Mpu::WTRA_index) // Attribute index - Write-Through, Read-allocate
+        },
+        {
+            // ITCM (S)
+            ARM_MPU_RBAR(0x10000000,      // Base
+                         ARM_MPU_SH_NON,  // Non-shareable
+                         1,               // Read-Only
+                         1,               // Non-Privileged
+                         0),              // eXecute Never disabled
+            ARM_MPU_RLAR(0x10007fff,      // Limit
+                         Mpu::WTRA_index) // Attribute index - Write-Through, Read-allocate
+        },
+        {
+            // DTCM (NS)
+            ARM_MPU_RBAR(0x20000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         1),                // eXecute Never enabled
+            ARM_MPU_RLAR(0x20007fff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // DTCM (S)
+            ARM_MPU_RBAR(0x30000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         1),                // eXecute Never enabled
+            ARM_MPU_RLAR(0x30007fff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // FPGA DATA SRAM; BRAM (NS)
+            ARM_MPU_RBAR(0x01000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         0),                // eXecute Never disabled
+            ARM_MPU_RLAR(0x011fffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // FPGA DATA SRAM; BRAM (S)
+            ARM_MPU_RBAR(0x11000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         0),                // eXecute Never disabled
+            ARM_MPU_RLAR(0x111fffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // SSE-300 internal SRAM (NS)
+            ARM_MPU_RBAR(0x21000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         0),                // eXecute Never disabled
+            ARM_MPU_RLAR(0x213fffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // SSE-300 internal SRAM (S)
+            ARM_MPU_RBAR(0x31000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         0),                // eXecute Never disabled
+            ARM_MPU_RLAR(0x313fffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // DDR (NS)
+            ARM_MPU_RBAR(0x60000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         1),                // eXecute Never enabled
+            ARM_MPU_RLAR(0x6fffffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        },
+        {
+            // DDR (S)
+            ARM_MPU_RBAR(0x70000000,        // Base
+                         ARM_MPU_SH_NON,    // Non-shareable
+                         0,                 // Read-Write
+                         1,                 // Non-Privileged
+                         1),                // eXecute Never enabled
+            ARM_MPU_RLAR(0x7fffffff,        // Limit
+                         Mpu::WBWARA_index) // Attribute index - Write-Back, Write-Allocate, Read-allocate
+        }};
+
+    // Setup MPU configuration
+    Mpu::loadAndEnableConfig(&mpuConfig[0], mpuConfig.size());
+
+#if defined(CPU_CACHE_ENABLE) && defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+    SCB_EnableICache();
+    SCB_EnableDCache();
+#endif
+}
+
+} // namespace EthosU