diff --git a/example/FVP_Audio/board/Corstone-300/Board-U55.clayer.yml b/example/FVP_Audio/board/Corstone-300/Board-U55.clayer.yml index 47d528c6..17fca191 100644 --- a/example/FVP_Audio/board/Corstone-300/Board-U55.clayer.yml +++ b/example/FVP_Audio/board/Corstone-300/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 128 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 128 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Audio/board/Corstone-300/Board-U65.clayer.yml b/example/FVP_Audio/board/Corstone-300/Board-U65.clayer.yml index 142bf2e8..b4b8f19a 100644 --- a/example/FVP_Audio/board/Corstone-300/Board-U65.clayer.yml +++ b/example/FVP_Audio/board/Corstone-300/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 256 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Audio/board/Corstone-300/Board.clayer.yml b/example/FVP_Audio/board/Corstone-300/Board.clayer.yml index bfab0681..7475d525 100644 --- a/example/FVP_Audio/board/Corstone-300/Board.clayer.yml +++ b/example/FVP_Audio/board/Corstone-300/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-300 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -23,9 +23,9 @@ layer: - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,8 +54,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Audio/board/Corstone-300/README.md b/example/FVP_Audio/board/Corstone-300/README.md index a5f90047..420e25bf 100644 --- a/example/FVP_Audio/board/Corstone-300/README.md +++ b/example/FVP_Audio/board/Corstone-300/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-300-FVP -## Board Layer for Corstone-300 FVP +## Board Layers for Corstone-300 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-300-FVP device: ARM::SSE-300-MPS3 ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src +++ b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src index 545300e9..7ac73375 100644 --- a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src +++ b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Audio/board/Corstone-300/regions_SSE-300.h b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h similarity index 100% rename from example/FVP_Audio/board/Corstone-300/regions_SSE-300.h rename to example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Audio/board/Corstone-300/sse300_memmap_ns.h b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h similarity index 100% rename from example/FVP_Audio/board/Corstone-300/sse300_memmap_ns.h rename to example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h diff --git a/example/FVP_Audio/board/Corstone-300/sse300_memmap_s.h b/example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h similarity index 100% rename from example/FVP_Audio/board/Corstone-300/sse300_memmap_s.h rename to example/FVP_Audio/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h diff --git a/example/FVP_Audio/board/Corstone-300/ethos_setup.c b/example/FVP_Audio/board/Corstone-300/ethos_setup.c index f154c77b..d4033b3a 100644 --- a/example/FVP_Audio/board/Corstone-300/ethos_setup.c +++ b/example/FVP_Audio/board/Corstone-300/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,8 +54,9 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Audio/board/Corstone-300/ethosu_dcache.c b/example/FVP_Audio/board/Corstone-300/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Audio/board/Corstone-300/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Audio/board/Corstone-300/ethosu_os_rtos2.c b/example/FVP_Audio/board/Corstone-300/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Audio/board/Corstone-300/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Audio/board/Corstone-300/main.c b/example/FVP_Audio/board/Corstone-300/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Audio/board/Corstone-300/main.c +++ b/example/FVP_Audio/board/Corstone-300/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Audio/board/Corstone-300/main.h b/example/FVP_Audio/board/Corstone-300/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Audio/board/Corstone-300/main.h +++ b/example/FVP_Audio/board/Corstone-300/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Audio/board/Corstone-310/Board-U55.clayer.yml b/example/FVP_Audio/board/Corstone-310/Board-U55.clayer.yml index 0141566e..2d5d613f 100644 --- a/example/FVP_Audio/board/Corstone-310/Board-U55.clayer.yml +++ b/example/FVP_Audio/board/Corstone-310/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Audio/board/Corstone-310/Board-U65.clayer.yml b/example/FVP_Audio/board/Corstone-310/Board-U65.clayer.yml index 0b62c4fb..16db95d4 100644 --- a/example/FVP_Audio/board/Corstone-310/Board-U65.clayer.yml +++ b/example/FVP_Audio/board/Corstone-310/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Audio/board/Corstone-310/Board.clayer.yml b/example/FVP_Audio/board/Corstone-310/Board.clayer.yml index 00edcbd0..c8636bed 100644 --- a/example/FVP_Audio/board/Corstone-310/Board.clayer.yml +++ b/example/FVP_Audio/board/Corstone-310/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-310 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-310.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Audio/board/Corstone-310/README.md b/example/FVP_Audio/board/Corstone-310/README.md index 551fdac5..cea338bd 100644 --- a/example/FVP_Audio/board/Corstone-310/README.md +++ b/example/FVP_Audio/board/Corstone-310/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-310 -## Board Layer for Corstone-310 FVP +## Board Layers for Corstone-310 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-310 device: ARM::SSE-310-MPS3_FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src index ac2c3c65..3c82dcb4 100644 --- a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src +++ b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -67,11 +67,8 @@ LR_ROM0 __ROM0_BASE __ROM0_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -101,8 +98,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src index e7ec9d02..cdbf0a94 100644 --- a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src @@ -78,6 +78,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -316,6 +322,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src index 3f8cf75b..1ad41354 100644 --- a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -314,8 +314,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -327,7 +326,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src index ea02d531..639d4295 100644 --- a/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src +++ b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -42,8 +42,6 @@ define memory mem with size = 4G; define region ROM3_region = []; #endif -define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_region; - #if __RAM0_SIZE > 0 define region RAM0_region = mem:[from __RAM0_BASE to (__RAM0_BASE+__RAM0_SIZE-1)]; #else @@ -68,8 +66,6 @@ define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_regio define region RAM3_region = []; #endif -define region RAM_region = RAM0_region | RAM1_region | RAM2_region | RAM3_region; - do not initialize { section .noinit }; initialize by copy { readwrite }; if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) @@ -80,15 +76,37 @@ if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) place at address mem:__ROM0_BASE { readonly section .intvec }; -if (!isempty(ROM_region)) +if (!isempty(ROM0_region)) { - place in ROM_region { readonly }; + place in ROM0_region { readonly }; } -if (!isempty(RAM_region)) +if (!isempty(RAM0_region)) { define block CSTACK with alignment = 8, size = __STACK_SIZE { }; define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; - place in RAM_region { readwrite, block CSTACK, block PROC_STACK, block HEAP }; + place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else + place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Audio/board/Corstone-310/regions_SSE-310.h b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h similarity index 100% rename from example/FVP_Audio/board/Corstone-310/regions_SSE-310.h rename to example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Audio/board/Corstone-310/sse310_memmap_ns.h b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h similarity index 100% rename from example/FVP_Audio/board/Corstone-310/sse310_memmap_ns.h rename to example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h diff --git a/example/FVP_Audio/board/Corstone-310/sse310_memmap_s.h b/example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h similarity index 100% rename from example/FVP_Audio/board/Corstone-310/sse310_memmap_s.h rename to example/FVP_Audio/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h diff --git a/example/FVP_Audio/board/Corstone-310/ethos_setup.c b/example/FVP_Audio/board/Corstone-310/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Audio/board/Corstone-310/ethos_setup.c +++ b/example/FVP_Audio/board/Corstone-310/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Audio/board/Corstone-310/ethosu_dcache.c b/example/FVP_Audio/board/Corstone-310/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Audio/board/Corstone-310/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Audio/board/Corstone-310/ethosu_os_rtos2.c b/example/FVP_Audio/board/Corstone-310/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Audio/board/Corstone-310/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Audio/board/Corstone-310/main.c b/example/FVP_Audio/board/Corstone-310/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Audio/board/Corstone-310/main.c +++ b/example/FVP_Audio/board/Corstone-310/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Audio/board/Corstone-310/main.h b/example/FVP_Audio/board/Corstone-310/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Audio/board/Corstone-310/main.h +++ b/example/FVP_Audio/board/Corstone-310/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Audio/board/Corstone-315/Board-U65.clayer.yml b/example/FVP_Audio/board/Corstone-315/Board-U65.clayer.yml index a4f57c54..4926cf82 100644 --- a/example/FVP_Audio/board/Corstone-315/Board-U65.clayer.yml +++ b/example/FVP_Audio/board/Corstone-315/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-315 FVP for AI/ML with Ethos U65 for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-315.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -52,14 +53,18 @@ layer: - component: Device:Native Driver:Timeout - component: Device:Native Driver:UART - - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Audio/board/Corstone-315/Board.clayer.yml b/example/FVP_Audio/board/Corstone-315/Board.clayer.yml index f9b1bcae..13622db5 100644 --- a/example/FVP_Audio/board/Corstone-315/Board.clayer.yml +++ b/example/FVP_Audio/board/Corstone-315/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-315 FVP for AI/ML for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-315.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Audio/board/Corstone-315/README.md b/example/FVP_Audio/board/Corstone-315/README.md index 3c8dd2aa..f7a0c014 100644 --- a/example/FVP_Audio/board/Corstone-315/README.md +++ b/example/FVP_Audio/board/Corstone-315/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-315 -## Board Layer for Corstone-315 FVP +## Board Layers for Corstone-315 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-315 device: ARM::SSE-315-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +51,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src +++ b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Audio/board/Corstone-315/regions_SSE-315.h b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h similarity index 100% rename from example/FVP_Audio/board/Corstone-315/regions_SSE-315.h rename to example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Audio/board/Corstone-315/sse315_memmap_ns.h b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h similarity index 100% rename from example/FVP_Audio/board/Corstone-315/sse315_memmap_ns.h rename to example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h diff --git a/example/FVP_Audio/board/Corstone-315/sse315_memmap_s.h b/example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h similarity index 100% rename from example/FVP_Audio/board/Corstone-315/sse315_memmap_s.h rename to example/FVP_Audio/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h diff --git a/example/FVP_Audio/board/Corstone-315/ethos_setup.c b/example/FVP_Audio/board/Corstone-315/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Audio/board/Corstone-315/ethos_setup.c +++ b/example/FVP_Audio/board/Corstone-315/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Audio/board/Corstone-315/ethosu_dcache.c b/example/FVP_Audio/board/Corstone-315/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Audio/board/Corstone-315/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Audio/board/Corstone-315/ethosu_os_rtos2.c b/example/FVP_Audio/board/Corstone-315/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Audio/board/Corstone-315/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Audio/board/Corstone-315/main.c b/example/FVP_Audio/board/Corstone-315/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Audio/board/Corstone-315/main.c +++ b/example/FVP_Audio/board/Corstone-315/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Audio/board/Corstone-315/main.h b/example/FVP_Audio/board/Corstone-315/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Audio/board/Corstone-315/main.h +++ b/example/FVP_Audio/board/Corstone-315/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Audio/board/Corstone-320/Board-U85.clayer.yml b/example/FVP_Audio/board/Corstone-320/Board-U85.clayer.yml index 0426a2c1..2fe6528f 100644 --- a/example/FVP_Audio/board/Corstone-320/Board-U85.clayer.yml +++ b/example/FVP_Audio/board/Corstone-320/Board-U85.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U85 + description: Configuration of SSE-320 FVP for AI/ML with Ethos U85 for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -17,18 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-320.h\" - - ETHOSU_MACS: 256 - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Audio/board/Corstone-320/Board.clayer.yml b/example/FVP_Audio/board/Corstone-320/Board.clayer.yml index ccf943ba..4540ba1d 100644 --- a/example/FVP_Audio/board/Corstone-320/Board.clayer.yml +++ b/example/FVP_Audio/board/Corstone-320/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-320 FVP for AI/ML for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -20,13 +20,12 @@ layer: define: - CMSIS_target_header: \"Corstone-320.h\" - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Audio/board/Corstone-320/Corstone-320.h b/example/FVP_Audio/board/Corstone-320/Corstone-320.h index 456d842d..f41a3813 100644 --- a/example/FVP_Audio/board/Corstone-320/Corstone-320.h +++ b/example/FVP_Audio/board/Corstone-320/Corstone-320.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_320_H_ #define CORSTONE_320_H_ diff --git a/example/FVP_Audio/board/Corstone-320/README.md b/example/FVP_Audio/board/Corstone-320/README.md index aa8836fe..c31a72f1 100644 --- a/example/FVP_Audio/board/Corstone-320/README.md +++ b/example/FVP_Audio/board/Corstone-320/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-320 -## Board Layer for Corstone-320 FVP +## Board Layers for Corstone-320 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-320 device: ARM::SSE-320-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U85.clayer.yml | With Ethos-U85 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,14 +51,14 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-320 FVP without Ethos-U or with Ethos-U85 +| fvp_config.txt | Corstone-320 FVP without or with an Ethos-U85-256 ### Python Requirements diff --git a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h index 3a68938f..19e2c883 100644 --- a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h +++ b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -64,14 +64,8 @@ /* ARM UART Controller CMSDK */ #ifdef RTE_USART0 #define UART0_CMSDK_S -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP; -#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S_TMP -#else #define UART0_CMSDK_DEV UART0_CMSDK_DEV_S #endif -#endif #ifdef RTE_USART1 #define UART1_CMSDK_S #define UART1_CMSDK_DEV UART1_CMSDK_DEV_S diff --git a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src +++ b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Audio/board/Corstone-320/regions_SSE-320.h b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h similarity index 100% rename from example/FVP_Audio/board/Corstone-320/regions_SSE-320.h rename to example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Audio/board/Corstone-320/sse320_memmap_ns.h b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h similarity index 100% rename from example/FVP_Audio/board/Corstone-320/sse320_memmap_ns.h rename to example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h diff --git a/example/FVP_Audio/board/Corstone-320/sse320_memmap_s.h b/example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h similarity index 100% rename from example/FVP_Audio/board/Corstone-320/sse320_memmap_s.h rename to example/FVP_Audio/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h diff --git a/example/FVP_Audio/board/Corstone-320/ethos_setup.c b/example/FVP_Audio/board/Corstone-320/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Audio/board/Corstone-320/ethos_setup.c +++ b/example/FVP_Audio/board/Corstone-320/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Audio/board/Corstone-320/ethosu_dcache.c b/example/FVP_Audio/board/Corstone-320/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Audio/board/Corstone-320/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Audio/board/Corstone-320/ethosu_os_rtos2.c b/example/FVP_Audio/board/Corstone-320/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Audio/board/Corstone-320/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Audio/board/Corstone-320/fvp_config.txt b/example/FVP_Audio/board/Corstone-320/fvp_config.txt index d40b2d89..1f010c81 100644 --- a/example/FVP_Audio/board/Corstone-320/fvp_config.txt +++ b/example/FVP_Audio/board/Corstone-320/fvp_config.txt @@ -1,6 +1,7 @@ # Parameters: # instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] #------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.extra_args="--fast" # (string, init-time) default = '' : To activate fast processing mode, which significantly improves the performance of the model, set this parameter to "--fast". In fast mode, NPU performance counters are not representative of counters on real hardware. We recommend you do not use any other value without instructions from Arm Technical Support. mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] mps4_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr mps4_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected diff --git a/example/FVP_Audio/board/Corstone-320/main.c b/example/FVP_Audio/board/Corstone-320/main.c index 6d2b31ac..302d89f2 100644 --- a/example/FVP_Audio/board/Corstone-320/main.c +++ b/example/FVP_Audio/board/Corstone-320/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,32 +14,13 @@ * 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 "RTE_Components.h" #include CMSIS_device_header #include "main.h" -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -#include "uart_cmsdk_drv.h" - -static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S_TMP = { - .base = 0x58203000 + 0x01100000, - .default_baudrate = 115200 -}; -static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S_TMP = { - .state = 0, - .system_clk = 0, - .baudrate = 0 -}; -struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP = { - &(UART0_CMSDK_DEV_CFG_S_TMP), - &(UART0_CMSDK_DEV_DATA_S_TMP) -}; -#endif - int main (void) { /* Initialize STDIO */ @@ -50,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Audio/board/Corstone-320/main.h b/example/FVP_Audio/board/Corstone-320/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Audio/board/Corstone-320/main.h +++ b/example/FVP_Audio/board/Corstone-320/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Audio/project/FVP_Audio.cproject.yml b/example/FVP_Audio/project/FVP_Audio.cproject.yml index d51459c0..37f6f51a 100644 --- a/example/FVP_Audio/project/FVP_Audio.cproject.yml +++ b/example/FVP_Audio/project/FVP_Audio.cproject.yml @@ -4,7 +4,7 @@ project: # List the packs that define the project software components. packs: - - pack: ARM::CMSIS@>=6.0.0 + - pack: ARM::CMSIS@^6.0.0 - pack: ARM::CMSIS-RTX # List connections used to identify compatible software layers. diff --git a/example/FVP_Hello/FVP_Hello.csolution.yml b/example/FVP_Hello/FVP_Hello.csolution.yml index c306f9d5..e59fe1eb 100644 --- a/example/FVP_Hello/FVP_Hello.csolution.yml +++ b/example/FVP_Hello/FVP_Hello.csolution.yml @@ -1,5 +1,6 @@ # A solution is a collection of related projects that share same base configuration. solution: + description: Hello World example solution created-for: CMSIS-Toolbox@2.12.0 cdefault: # use CMSIS-Toolbox default Compiler options @@ -7,16 +8,8 @@ solution: select-compiler: - compiler: AC6 - compiler: GCC - - compiler: IAR - compiler: CLANG - - # List of miscellaneous tool-specific controls - misc: - - for-compiler: AC6 # GDB requires DWARF 5, remove when using uVision Debugger - C-CPP: - - -gdwarf-5 - ASM: - - -gdwarf-5 + - compiler: IAR # List the packs that define the device and/or board. packs: diff --git a/example/FVP_Hello/README.md b/example/FVP_Hello/README.md index 88d86296..73869924 100644 --- a/example/FVP_Hello/README.md +++ b/example/FVP_Hello/README.md @@ -1,12 +1,15 @@ # Hello World Application + This example prints "Hello World" and a counter value via the standard output. It can be used as a starting point when developing new applications. -### Functionality +## Functionality + The application initializes CMSIS-RTOS2, creates the main application thread and starts the RTOS scheduler. The application thread increments a counter and outputs it together with the counter value. -### Output +## Output + The "Hello World" string, along with the counter value, is output via printf and -retargeted to the debug console. \ No newline at end of file +retargeted to the debug console. diff --git a/example/FVP_Hello/board/Corstone-300/Board-U55.clayer.yml b/example/FVP_Hello/board/Corstone-300/Board-U55.clayer.yml index 47d528c6..17fca191 100644 --- a/example/FVP_Hello/board/Corstone-300/Board-U55.clayer.yml +++ b/example/FVP_Hello/board/Corstone-300/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 128 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 128 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Hello/board/Corstone-300/Board-U65.clayer.yml b/example/FVP_Hello/board/Corstone-300/Board-U65.clayer.yml index 142bf2e8..b4b8f19a 100644 --- a/example/FVP_Hello/board/Corstone-300/Board-U65.clayer.yml +++ b/example/FVP_Hello/board/Corstone-300/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 256 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Hello/board/Corstone-300/Board.clayer.yml b/example/FVP_Hello/board/Corstone-300/Board.clayer.yml index bfab0681..7475d525 100644 --- a/example/FVP_Hello/board/Corstone-300/Board.clayer.yml +++ b/example/FVP_Hello/board/Corstone-300/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-300 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -23,9 +23,9 @@ layer: - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,8 +54,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Hello/board/Corstone-300/README.md b/example/FVP_Hello/board/Corstone-300/README.md index a5f90047..420e25bf 100644 --- a/example/FVP_Hello/board/Corstone-300/README.md +++ b/example/FVP_Hello/board/Corstone-300/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-300-FVP -## Board Layer for Corstone-300 FVP +## Board Layers for Corstone-300 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-300-FVP device: ARM::SSE-300-MPS3 ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src +++ b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src new file mode 100644 index 00000000..7ac73375 --- /dev/null +++ b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src @@ -0,0 +1,406 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx!w) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx!w) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx!w) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx!w) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (w!rx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (w!rx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (w!rx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (w!rx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +ENTRY(Reset_Handler) + +PHDRS +{ + boot PT_LOAD; + text PT_LOAD; + ram PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif +} + +SECTIONS +{ + .init : { + KEEP (*(.vectors)) + + /* Disable by default + * + * *.init.enter contains a vector table provided by picolibc, + * whereas CMSIS already provides a vector table via .vectors + */ + /* + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + */ + + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ROM0 AT>ROM0 :boot + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .veneers : + { + . = ALIGN(32); + KEEP(*(.gnu.sgstubs)) + } > ROM0 AT>ROM0 :boot +#endif + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + *(.data.rel.ro .data.rel.ro.*) + *(.got .got.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + /* lists of constructors and destructors */ + PROVIDE_HIDDEN ( __bothinit_array_start = . ); + PROVIDE_HIDDEN ( __preinit_array_start = . ); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN ( __preinit_array_end = . ); + + PROVIDE_HIDDEN ( __init_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN ( __init_array_end = . ); + PROVIDE_HIDDEN ( __bothinit_array_end = . ); + + PROVIDE_HIDDEN ( __fini_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array .dtors)) + PROVIDE_HIDDEN ( __fini_array_end = . ); + + } >ROM1 AT>ROM1 :text + + .toc : { + *(.toc .toc.*) + } >ROM1 AT>ROM1 :text + + /* additional sections when compiling with C++ exception support */ + + .except_ordered : { + *(.gcc_except_table *.gcc_except_table.*) + KEEP (*(.eh_frame .eh_frame.*)) + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM1 AT>ROM1 :text + + .except_unordered : { + . = ALIGN(8); + + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + PROVIDE(__exidx_end = .); + } >ROM1 AT>ROM1 :text + + + /* + * Data values which are preserved across reset + */ + .preserve (NOLOAD) : { + PROVIDE(__preserve_start__ = .); + KEEP(*(SORT_BY_NAME(.preserve.*))) + KEEP(*(.preserve)) + PROVIDE(__preserve_end__ = .); + } >RAM0 AT>RAM0 :ram + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >RAM0 AT>ROM1 :ram_init + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + /* Thread local initialized data. This gets + * space allocated as it is expected to be placed + * in ram to be used as a template for TLS data blocks + * allocated at runtime. We're slightly abusing that + * by placing the data in flash where it will be copied + * into the allocate ram addresses by the existing + * data initialization code in crt0 + */ + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM0 AT>ROM1 :tls :ram_init + PROVIDE( __tls_base = ADDR(.tdata)); + PROVIDE( __tdata_start = ADDR(.tdata)); + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata),ALIGNOF(.tbss)) ); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + + .tbss (NOLOAD) : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM0 AT>RAM0 :tls :ram + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __tbss_start = ADDR(.tbss)); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + /* + * The linker special cases .tbss segments which are + * identified as segments which are not loaded and are + * thread_local. + * + * For these segments, the linker does not advance 'dot' + * across them. We actually need memory allocated for tbss, + * so we create a special segment here just to make room + */ + /* + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM0 AT>RAM0 :ram + */ + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the end of this section, so next can start on aligned address */ + . = ALIGN(8); + __bss_end = .; + } >RAM0 AT>RAM0 :ram + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit (NOLOAD) : { + __noinit_start__ = .; + *(.noinit) + *(.noinit.*) + + /* Align the end of this section, so next (heap) can start on aligned address */ + . = ALIGN(8); + __noinit_end__ = .; + } >RAM0 AT>RAM0 :ram + + PROVIDE( __end = . ); + PROVIDE( _end = . ); + PROVIDE( end = . ); + + /* Make the rest of memory available for heap storage */ + PROVIDE (__heap_start = __end); +#ifdef __HEAP_SIZE + PROVIDE (__heap_end = __heap_start + __HEAP_SIZE); + PROVIDE (__heap_size = __HEAP_SIZE); +#else + PROVIDE (__heap_end = __stack - __STACK_SIZE); + PROVIDE (__heap_size = __heap_end - __heap_start); +#endif + .heap (NOLOAD) : { + . += __heap_size; + } >RAM0 :ram + + /* Define a stack region to make sure it fits in memory */ + PROVIDE(__stack = ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE); + PROVIDE(__stack_limit = __stack - __STACK_SIZE); + .stack (__stack_limit) (NOLOAD) : { + . += __STACK_SIZE; + } >RAM0 :ram + +#if __STACKSEAL_SIZE > 0 + PROVIDE(__stack_seal = __stack); + .stackseal (__stack) (NOLOAD) : + { + . += __STACKSEAL_SIZE; + } >RAM0 :ram +#endif + + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + + /* Throw away C++ exception handling information */ + + /* + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} +/* + * Check that sections that are copied from flash to RAM have matching + * padding, so that a single memcpy() of __data_size copies the correct bytes. + */ +ASSERT( __data_size == __data_source_size, + "ERROR: .data/.tdata flash size does not match RAM size"); diff --git a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src +++ b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Hello/board/Corstone-300/regions_SSE-300.h b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h similarity index 100% rename from example/FVP_Hello/board/Corstone-300/regions_SSE-300.h rename to example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Hello/board/Corstone-300/sse300_memmap_ns.h b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h similarity index 100% rename from example/FVP_Hello/board/Corstone-300/sse300_memmap_ns.h rename to example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h diff --git a/example/FVP_Hello/board/Corstone-300/sse300_memmap_s.h b/example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h similarity index 100% rename from example/FVP_Hello/board/Corstone-300/sse300_memmap_s.h rename to example/FVP_Hello/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h diff --git a/example/FVP_Hello/board/Corstone-300/ethos_setup.c b/example/FVP_Hello/board/Corstone-300/ethos_setup.c index f154c77b..d4033b3a 100644 --- a/example/FVP_Hello/board/Corstone-300/ethos_setup.c +++ b/example/FVP_Hello/board/Corstone-300/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,8 +54,9 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Hello/board/Corstone-300/ethosu_dcache.c b/example/FVP_Hello/board/Corstone-300/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Hello/board/Corstone-300/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Hello/board/Corstone-300/ethosu_os_rtos2.c b/example/FVP_Hello/board/Corstone-300/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Hello/board/Corstone-300/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Hello/board/Corstone-300/main.c b/example/FVP_Hello/board/Corstone-300/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Hello/board/Corstone-300/main.c +++ b/example/FVP_Hello/board/Corstone-300/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Hello/board/Corstone-300/main.h b/example/FVP_Hello/board/Corstone-300/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Hello/board/Corstone-300/main.h +++ b/example/FVP_Hello/board/Corstone-300/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Hello/board/Corstone-310/Board-U55.clayer.yml b/example/FVP_Hello/board/Corstone-310/Board-U55.clayer.yml index 0141566e..2d5d613f 100644 --- a/example/FVP_Hello/board/Corstone-310/Board-U55.clayer.yml +++ b/example/FVP_Hello/board/Corstone-310/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Hello/board/Corstone-310/Board-U65.clayer.yml b/example/FVP_Hello/board/Corstone-310/Board-U65.clayer.yml index 0b62c4fb..16db95d4 100644 --- a/example/FVP_Hello/board/Corstone-310/Board-U65.clayer.yml +++ b/example/FVP_Hello/board/Corstone-310/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Hello/board/Corstone-310/Board.clayer.yml b/example/FVP_Hello/board/Corstone-310/Board.clayer.yml index 00edcbd0..c8636bed 100644 --- a/example/FVP_Hello/board/Corstone-310/Board.clayer.yml +++ b/example/FVP_Hello/board/Corstone-310/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-310 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-310.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Hello/board/Corstone-310/README.md b/example/FVP_Hello/board/Corstone-310/README.md index 551fdac5..cea338bd 100644 --- a/example/FVP_Hello/board/Corstone-310/README.md +++ b/example/FVP_Hello/board/Corstone-310/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-310 -## Board Layer for Corstone-310 FVP +## Board Layers for Corstone-310 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-310 device: ARM::SSE-310-MPS3_FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src index ac2c3c65..3c82dcb4 100644 --- a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src +++ b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -67,11 +67,8 @@ LR_ROM0 __ROM0_BASE __ROM0_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -101,8 +98,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src index e7ec9d02..cdbf0a94 100644 --- a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src @@ -78,6 +78,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -316,6 +322,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src index 3f8cf75b..1ad41354 100644 --- a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -314,8 +314,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -327,7 +326,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src index ea02d531..639d4295 100644 --- a/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src +++ b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -42,8 +42,6 @@ define memory mem with size = 4G; define region ROM3_region = []; #endif -define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_region; - #if __RAM0_SIZE > 0 define region RAM0_region = mem:[from __RAM0_BASE to (__RAM0_BASE+__RAM0_SIZE-1)]; #else @@ -68,8 +66,6 @@ define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_regio define region RAM3_region = []; #endif -define region RAM_region = RAM0_region | RAM1_region | RAM2_region | RAM3_region; - do not initialize { section .noinit }; initialize by copy { readwrite }; if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) @@ -80,15 +76,37 @@ if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) place at address mem:__ROM0_BASE { readonly section .intvec }; -if (!isempty(ROM_region)) +if (!isempty(ROM0_region)) { - place in ROM_region { readonly }; + place in ROM0_region { readonly }; } -if (!isempty(RAM_region)) +if (!isempty(RAM0_region)) { define block CSTACK with alignment = 8, size = __STACK_SIZE { }; define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; - place in RAM_region { readwrite, block CSTACK, block PROC_STACK, block HEAP }; + place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else + place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Hello/board/Corstone-310/regions_SSE-310.h b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h similarity index 100% rename from example/FVP_Hello/board/Corstone-310/regions_SSE-310.h rename to example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Hello/board/Corstone-310/sse310_memmap_ns.h b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h similarity index 100% rename from example/FVP_Hello/board/Corstone-310/sse310_memmap_ns.h rename to example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h diff --git a/example/FVP_Hello/board/Corstone-310/sse310_memmap_s.h b/example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h similarity index 100% rename from example/FVP_Hello/board/Corstone-310/sse310_memmap_s.h rename to example/FVP_Hello/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h diff --git a/example/FVP_Hello/board/Corstone-310/ethos_setup.c b/example/FVP_Hello/board/Corstone-310/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Hello/board/Corstone-310/ethos_setup.c +++ b/example/FVP_Hello/board/Corstone-310/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Hello/board/Corstone-310/ethosu_dcache.c b/example/FVP_Hello/board/Corstone-310/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Hello/board/Corstone-310/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Hello/board/Corstone-310/ethosu_os_rtos2.c b/example/FVP_Hello/board/Corstone-310/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Hello/board/Corstone-310/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Hello/board/Corstone-310/main.c b/example/FVP_Hello/board/Corstone-310/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Hello/board/Corstone-310/main.c +++ b/example/FVP_Hello/board/Corstone-310/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Hello/board/Corstone-310/main.h b/example/FVP_Hello/board/Corstone-310/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Hello/board/Corstone-310/main.h +++ b/example/FVP_Hello/board/Corstone-310/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Hello/board/Corstone-315/Board-U65.clayer.yml b/example/FVP_Hello/board/Corstone-315/Board-U65.clayer.yml index a4f57c54..4926cf82 100644 --- a/example/FVP_Hello/board/Corstone-315/Board-U65.clayer.yml +++ b/example/FVP_Hello/board/Corstone-315/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-315 FVP for AI/ML with Ethos U65 for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-315.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -52,14 +53,18 @@ layer: - component: Device:Native Driver:Timeout - component: Device:Native Driver:UART - - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Hello/board/Corstone-315/Board.clayer.yml b/example/FVP_Hello/board/Corstone-315/Board.clayer.yml index f9b1bcae..13622db5 100644 --- a/example/FVP_Hello/board/Corstone-315/Board.clayer.yml +++ b/example/FVP_Hello/board/Corstone-315/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-315 FVP for AI/ML for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-315.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Hello/board/Corstone-315/README.md b/example/FVP_Hello/board/Corstone-315/README.md index 3c8dd2aa..f7a0c014 100644 --- a/example/FVP_Hello/board/Corstone-315/README.md +++ b/example/FVP_Hello/board/Corstone-315/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-315 -## Board Layer for Corstone-315 FVP +## Board Layers for Corstone-315 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-315 device: ARM::SSE-315-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +51,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src +++ b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Hello/board/Corstone-315/regions_SSE-315.h b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h similarity index 100% rename from example/FVP_Hello/board/Corstone-315/regions_SSE-315.h rename to example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Hello/board/Corstone-315/sse315_memmap_ns.h b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h similarity index 100% rename from example/FVP_Hello/board/Corstone-315/sse315_memmap_ns.h rename to example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h diff --git a/example/FVP_Hello/board/Corstone-315/sse315_memmap_s.h b/example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h similarity index 100% rename from example/FVP_Hello/board/Corstone-315/sse315_memmap_s.h rename to example/FVP_Hello/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h diff --git a/example/FVP_Hello/board/Corstone-315/ethos_setup.c b/example/FVP_Hello/board/Corstone-315/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Hello/board/Corstone-315/ethos_setup.c +++ b/example/FVP_Hello/board/Corstone-315/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Hello/board/Corstone-315/ethosu_dcache.c b/example/FVP_Hello/board/Corstone-315/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Hello/board/Corstone-315/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Hello/board/Corstone-315/ethosu_os_rtos2.c b/example/FVP_Hello/board/Corstone-315/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Hello/board/Corstone-315/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Hello/board/Corstone-315/main.c b/example/FVP_Hello/board/Corstone-315/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Hello/board/Corstone-315/main.c +++ b/example/FVP_Hello/board/Corstone-315/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Hello/board/Corstone-315/main.h b/example/FVP_Hello/board/Corstone-315/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Hello/board/Corstone-315/main.h +++ b/example/FVP_Hello/board/Corstone-315/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Hello/board/Corstone-320/Board-U85.clayer.yml b/example/FVP_Hello/board/Corstone-320/Board-U85.clayer.yml index 0426a2c1..2fe6528f 100644 --- a/example/FVP_Hello/board/Corstone-320/Board-U85.clayer.yml +++ b/example/FVP_Hello/board/Corstone-320/Board-U85.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U85 + description: Configuration of SSE-320 FVP for AI/ML with Ethos U85 for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -17,18 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-320.h\" - - ETHOSU_MACS: 256 - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Hello/board/Corstone-320/Board.clayer.yml b/example/FVP_Hello/board/Corstone-320/Board.clayer.yml index ccf943ba..4540ba1d 100644 --- a/example/FVP_Hello/board/Corstone-320/Board.clayer.yml +++ b/example/FVP_Hello/board/Corstone-320/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-320 FVP for AI/ML for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -20,13 +20,12 @@ layer: define: - CMSIS_target_header: \"Corstone-320.h\" - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Hello/board/Corstone-320/Corstone-320.h b/example/FVP_Hello/board/Corstone-320/Corstone-320.h index 456d842d..f41a3813 100644 --- a/example/FVP_Hello/board/Corstone-320/Corstone-320.h +++ b/example/FVP_Hello/board/Corstone-320/Corstone-320.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_320_H_ #define CORSTONE_320_H_ diff --git a/example/FVP_Hello/board/Corstone-320/README.md b/example/FVP_Hello/board/Corstone-320/README.md index aa8836fe..c31a72f1 100644 --- a/example/FVP_Hello/board/Corstone-320/README.md +++ b/example/FVP_Hello/board/Corstone-320/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-320 -## Board Layer for Corstone-320 FVP +## Board Layers for Corstone-320 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-320 device: ARM::SSE-320-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U85.clayer.yml | With Ethos-U85 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,14 +51,14 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-320 FVP without Ethos-U or with Ethos-U85 +| fvp_config.txt | Corstone-320 FVP without or with an Ethos-U85-256 ### Python Requirements diff --git a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h index 3a68938f..19e2c883 100644 --- a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h +++ b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -64,14 +64,8 @@ /* ARM UART Controller CMSDK */ #ifdef RTE_USART0 #define UART0_CMSDK_S -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP; -#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S_TMP -#else #define UART0_CMSDK_DEV UART0_CMSDK_DEV_S #endif -#endif #ifdef RTE_USART1 #define UART1_CMSDK_S #define UART1_CMSDK_DEV UART1_CMSDK_DEV_S diff --git a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src +++ b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Hello/board/Corstone-320/regions_SSE-320.h b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h similarity index 100% rename from example/FVP_Hello/board/Corstone-320/regions_SSE-320.h rename to example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Hello/board/Corstone-320/sse320_memmap_ns.h b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h similarity index 100% rename from example/FVP_Hello/board/Corstone-320/sse320_memmap_ns.h rename to example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h diff --git a/example/FVP_Hello/board/Corstone-320/sse320_memmap_s.h b/example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h similarity index 100% rename from example/FVP_Hello/board/Corstone-320/sse320_memmap_s.h rename to example/FVP_Hello/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h diff --git a/example/FVP_Hello/board/Corstone-320/ethos_setup.c b/example/FVP_Hello/board/Corstone-320/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Hello/board/Corstone-320/ethos_setup.c +++ b/example/FVP_Hello/board/Corstone-320/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Hello/board/Corstone-320/ethosu_dcache.c b/example/FVP_Hello/board/Corstone-320/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Hello/board/Corstone-320/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Hello/board/Corstone-320/ethosu_os_rtos2.c b/example/FVP_Hello/board/Corstone-320/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Hello/board/Corstone-320/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Hello/board/Corstone-320/fvp_config.txt b/example/FVP_Hello/board/Corstone-320/fvp_config.txt index d40b2d89..1f010c81 100644 --- a/example/FVP_Hello/board/Corstone-320/fvp_config.txt +++ b/example/FVP_Hello/board/Corstone-320/fvp_config.txt @@ -1,6 +1,7 @@ # Parameters: # instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] #------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.extra_args="--fast" # (string, init-time) default = '' : To activate fast processing mode, which significantly improves the performance of the model, set this parameter to "--fast". In fast mode, NPU performance counters are not representative of counters on real hardware. We recommend you do not use any other value without instructions from Arm Technical Support. mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] mps4_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr mps4_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected diff --git a/example/FVP_Hello/board/Corstone-320/main.c b/example/FVP_Hello/board/Corstone-320/main.c index 6d2b31ac..302d89f2 100644 --- a/example/FVP_Hello/board/Corstone-320/main.c +++ b/example/FVP_Hello/board/Corstone-320/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,32 +14,13 @@ * 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 "RTE_Components.h" #include CMSIS_device_header #include "main.h" -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -#include "uart_cmsdk_drv.h" - -static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S_TMP = { - .base = 0x58203000 + 0x01100000, - .default_baudrate = 115200 -}; -static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S_TMP = { - .state = 0, - .system_clk = 0, - .baudrate = 0 -}; -struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP = { - &(UART0_CMSDK_DEV_CFG_S_TMP), - &(UART0_CMSDK_DEV_DATA_S_TMP) -}; -#endif - int main (void) { /* Initialize STDIO */ @@ -50,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Hello/board/Corstone-320/main.h b/example/FVP_Hello/board/Corstone-320/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Hello/board/Corstone-320/main.h +++ b/example/FVP_Hello/board/Corstone-320/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Hello/project/FVP_Hello.cproject.yml b/example/FVP_Hello/project/FVP_Hello.cproject.yml index 80abfa44..776d1fba 100644 --- a/example/FVP_Hello/project/FVP_Hello.cproject.yml +++ b/example/FVP_Hello/project/FVP_Hello.cproject.yml @@ -4,7 +4,7 @@ project: # List the packs that define the project software components. packs: - - pack: ARM::CMSIS@>=6.0.0 + - pack: ARM::CMSIS@^6.0.0 - pack: ARM::CMSIS-RTX # List connections used to identify compatible software layers. diff --git a/example/FVP_Video/README.md b/example/FVP_Video/README.md index 51dd8c36..cb72aadb 100644 --- a/example/FVP_Video/README.md +++ b/example/FVP_Video/README.md @@ -15,7 +15,7 @@ If input and output stream resolutions differ the input frame is centered within output frame and/or cropped when required. Streaming stops after receiving the `END_OF_STREAM` event or can be configured to -stop after `AUDIO_STREAM_DURATION` seconds. +stop after `VIDEO_STREAM_DURATION` seconds. The example uses CMSIS-RTOS2 for thread management and event-driven processing. diff --git a/example/FVP_Video/board/Corstone-300/Board-U55.clayer.yml b/example/FVP_Video/board/Corstone-300/Board-U55.clayer.yml index 47d528c6..17fca191 100644 --- a/example/FVP_Video/board/Corstone-300/Board-U55.clayer.yml +++ b/example/FVP_Video/board/Corstone-300/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 128 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 128 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Video/board/Corstone-300/Board-U65.clayer.yml b/example/FVP_Video/board/Corstone-300/Board-U65.clayer.yml index 142bf2e8..b4b8f19a 100644 --- a/example/FVP_Video/board/Corstone-300/Board-U65.clayer.yml +++ b/example/FVP_Video/board/Corstone-300/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 256 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Video/board/Corstone-300/Board.clayer.yml b/example/FVP_Video/board/Corstone-300/Board.clayer.yml index bfab0681..7475d525 100644 --- a/example/FVP_Video/board/Corstone-300/Board.clayer.yml +++ b/example/FVP_Video/board/Corstone-300/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-300 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -23,9 +23,9 @@ layer: - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,8 +54,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Video/board/Corstone-300/README.md b/example/FVP_Video/board/Corstone-300/README.md index a5f90047..420e25bf 100644 --- a/example/FVP_Video/board/Corstone-300/README.md +++ b/example/FVP_Video/board/Corstone-300/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-300-FVP -## Board Layer for Corstone-300 FVP +## Board Layers for Corstone-300 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-300-FVP device: ARM::SSE-300-MPS3 ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src +++ b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src index 545300e9..7ac73375 100644 --- a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src +++ b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Video/board/Corstone-300/regions_SSE-300.h b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h similarity index 100% rename from example/FVP_Video/board/Corstone-300/regions_SSE-300.h rename to example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/example/FVP_Video/board/Corstone-300/sse300_memmap_ns.h b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h similarity index 100% rename from example/FVP_Video/board/Corstone-300/sse300_memmap_ns.h rename to example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h diff --git a/example/FVP_Video/board/Corstone-300/sse300_memmap_s.h b/example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h similarity index 100% rename from example/FVP_Video/board/Corstone-300/sse300_memmap_s.h rename to example/FVP_Video/board/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h diff --git a/example/FVP_Video/board/Corstone-300/ethos_setup.c b/example/FVP_Video/board/Corstone-300/ethos_setup.c index f154c77b..d4033b3a 100644 --- a/example/FVP_Video/board/Corstone-300/ethos_setup.c +++ b/example/FVP_Video/board/Corstone-300/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,8 +54,9 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Video/board/Corstone-300/ethosu_dcache.c b/example/FVP_Video/board/Corstone-300/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Video/board/Corstone-300/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Video/board/Corstone-300/ethosu_os_rtos2.c b/example/FVP_Video/board/Corstone-300/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Video/board/Corstone-300/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Video/board/Corstone-300/main.c b/example/FVP_Video/board/Corstone-300/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Video/board/Corstone-300/main.c +++ b/example/FVP_Video/board/Corstone-300/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Video/board/Corstone-300/main.h b/example/FVP_Video/board/Corstone-300/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Video/board/Corstone-300/main.h +++ b/example/FVP_Video/board/Corstone-300/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Video/board/Corstone-310/Board-U55.clayer.yml b/example/FVP_Video/board/Corstone-310/Board-U55.clayer.yml index 0141566e..2d5d613f 100644 --- a/example/FVP_Video/board/Corstone-310/Board-U55.clayer.yml +++ b/example/FVP_Video/board/Corstone-310/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Video/board/Corstone-310/Board-U65.clayer.yml b/example/FVP_Video/board/Corstone-310/Board-U65.clayer.yml index 0b62c4fb..16db95d4 100644 --- a/example/FVP_Video/board/Corstone-310/Board-U65.clayer.yml +++ b/example/FVP_Video/board/Corstone-310/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Video/board/Corstone-310/Board.clayer.yml b/example/FVP_Video/board/Corstone-310/Board.clayer.yml index 00edcbd0..c8636bed 100644 --- a/example/FVP_Video/board/Corstone-310/Board.clayer.yml +++ b/example/FVP_Video/board/Corstone-310/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-310 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-310.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Video/board/Corstone-310/README.md b/example/FVP_Video/board/Corstone-310/README.md index 551fdac5..cea338bd 100644 --- a/example/FVP_Video/board/Corstone-310/README.md +++ b/example/FVP_Video/board/Corstone-310/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-310 -## Board Layer for Corstone-310 FVP +## Board Layers for Corstone-310 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-310 device: ARM::SSE-310-MPS3_FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src index ac2c3c65..3c82dcb4 100644 --- a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src +++ b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -67,11 +67,8 @@ LR_ROM0 __ROM0_BASE __ROM0_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -101,8 +98,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src index e7ec9d02..cdbf0a94 100644 --- a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src @@ -78,6 +78,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -316,6 +322,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src index 3f8cf75b..1ad41354 100644 --- a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -314,8 +314,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -327,7 +326,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src index ea02d531..639d4295 100644 --- a/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src +++ b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -42,8 +42,6 @@ define memory mem with size = 4G; define region ROM3_region = []; #endif -define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_region; - #if __RAM0_SIZE > 0 define region RAM0_region = mem:[from __RAM0_BASE to (__RAM0_BASE+__RAM0_SIZE-1)]; #else @@ -68,8 +66,6 @@ define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_regio define region RAM3_region = []; #endif -define region RAM_region = RAM0_region | RAM1_region | RAM2_region | RAM3_region; - do not initialize { section .noinit }; initialize by copy { readwrite }; if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) @@ -80,15 +76,37 @@ if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) place at address mem:__ROM0_BASE { readonly section .intvec }; -if (!isempty(ROM_region)) +if (!isempty(ROM0_region)) { - place in ROM_region { readonly }; + place in ROM0_region { readonly }; } -if (!isempty(RAM_region)) +if (!isempty(RAM0_region)) { define block CSTACK with alignment = 8, size = __STACK_SIZE { }; define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; - place in RAM_region { readwrite, block CSTACK, block PROC_STACK, block HEAP }; + place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else + place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Video/board/Corstone-310/regions_SSE-310.h b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h similarity index 100% rename from example/FVP_Video/board/Corstone-310/regions_SSE-310.h rename to example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/example/FVP_Video/board/Corstone-310/sse310_memmap_ns.h b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h similarity index 100% rename from example/FVP_Video/board/Corstone-310/sse310_memmap_ns.h rename to example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h diff --git a/example/FVP_Video/board/Corstone-310/sse310_memmap_s.h b/example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h similarity index 100% rename from example/FVP_Video/board/Corstone-310/sse310_memmap_s.h rename to example/FVP_Video/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h diff --git a/example/FVP_Video/board/Corstone-310/ethos_setup.c b/example/FVP_Video/board/Corstone-310/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Video/board/Corstone-310/ethos_setup.c +++ b/example/FVP_Video/board/Corstone-310/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Video/board/Corstone-310/ethosu_dcache.c b/example/FVP_Video/board/Corstone-310/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Video/board/Corstone-310/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Video/board/Corstone-310/ethosu_os_rtos2.c b/example/FVP_Video/board/Corstone-310/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Video/board/Corstone-310/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Video/board/Corstone-310/main.c b/example/FVP_Video/board/Corstone-310/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Video/board/Corstone-310/main.c +++ b/example/FVP_Video/board/Corstone-310/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Video/board/Corstone-310/main.h b/example/FVP_Video/board/Corstone-310/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Video/board/Corstone-310/main.h +++ b/example/FVP_Video/board/Corstone-310/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Video/board/Corstone-315/Board-U65.clayer.yml b/example/FVP_Video/board/Corstone-315/Board-U65.clayer.yml index a4f57c54..4926cf82 100644 --- a/example/FVP_Video/board/Corstone-315/Board-U65.clayer.yml +++ b/example/FVP_Video/board/Corstone-315/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-315 FVP for AI/ML with Ethos U65 for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-315.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -52,14 +53,18 @@ layer: - component: Device:Native Driver:Timeout - component: Device:Native Driver:UART - - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Video/board/Corstone-315/Board.clayer.yml b/example/FVP_Video/board/Corstone-315/Board.clayer.yml index f9b1bcae..13622db5 100644 --- a/example/FVP_Video/board/Corstone-315/Board.clayer.yml +++ b/example/FVP_Video/board/Corstone-315/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-315 FVP for AI/ML for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-315.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Video/board/Corstone-315/README.md b/example/FVP_Video/board/Corstone-315/README.md index 3c8dd2aa..f7a0c014 100644 --- a/example/FVP_Video/board/Corstone-315/README.md +++ b/example/FVP_Video/board/Corstone-315/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-315 -## Board Layer for Corstone-315 FVP +## Board Layers for Corstone-315 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-315 device: ARM::SSE-315-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +51,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src +++ b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Video/board/Corstone-315/regions_SSE-315.h b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h similarity index 100% rename from example/FVP_Video/board/Corstone-315/regions_SSE-315.h rename to example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/example/FVP_Video/board/Corstone-315/sse315_memmap_ns.h b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h similarity index 100% rename from example/FVP_Video/board/Corstone-315/sse315_memmap_ns.h rename to example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h diff --git a/example/FVP_Video/board/Corstone-315/sse315_memmap_s.h b/example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h similarity index 100% rename from example/FVP_Video/board/Corstone-315/sse315_memmap_s.h rename to example/FVP_Video/board/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h diff --git a/example/FVP_Video/board/Corstone-315/ethos_setup.c b/example/FVP_Video/board/Corstone-315/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Video/board/Corstone-315/ethos_setup.c +++ b/example/FVP_Video/board/Corstone-315/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Video/board/Corstone-315/ethosu_dcache.c b/example/FVP_Video/board/Corstone-315/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Video/board/Corstone-315/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Video/board/Corstone-315/ethosu_os_rtos2.c b/example/FVP_Video/board/Corstone-315/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Video/board/Corstone-315/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Video/board/Corstone-315/main.c b/example/FVP_Video/board/Corstone-315/main.c index 69b34855..302d89f2 100644 --- a/example/FVP_Video/board/Corstone-315/main.c +++ b/example/FVP_Video/board/Corstone-315/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Video/board/Corstone-315/main.h b/example/FVP_Video/board/Corstone-315/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Video/board/Corstone-315/main.h +++ b/example/FVP_Video/board/Corstone-315/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Video/board/Corstone-320/Board-U85.clayer.yml b/example/FVP_Video/board/Corstone-320/Board-U85.clayer.yml index 0426a2c1..2fe6528f 100644 --- a/example/FVP_Video/board/Corstone-320/Board-U85.clayer.yml +++ b/example/FVP_Video/board/Corstone-320/Board-U85.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U85 + description: Configuration of SSE-320 FVP for AI/ML with Ethos U85 for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -17,18 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-320.h\" - - ETHOSU_MACS: 256 - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Video/board/Corstone-320/Board.clayer.yml b/example/FVP_Video/board/Corstone-320/Board.clayer.yml index ccf943ba..4540ba1d 100644 --- a/example/FVP_Video/board/Corstone-320/Board.clayer.yml +++ b/example/FVP_Video/board/Corstone-320/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-320 FVP for AI/ML for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -20,13 +20,12 @@ layer: define: - CMSIS_target_header: \"Corstone-320.h\" - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Video/board/Corstone-320/Corstone-320.h b/example/FVP_Video/board/Corstone-320/Corstone-320.h index 456d842d..f41a3813 100644 --- a/example/FVP_Video/board/Corstone-320/Corstone-320.h +++ b/example/FVP_Video/board/Corstone-320/Corstone-320.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_320_H_ #define CORSTONE_320_H_ diff --git a/example/FVP_Video/board/Corstone-320/README.md b/example/FVP_Video/board/Corstone-320/README.md index aa8836fe..c31a72f1 100644 --- a/example/FVP_Video/board/Corstone-320/README.md +++ b/example/FVP_Video/board/Corstone-320/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-320 -## Board Layer for Corstone-320 FVP +## Board Layers for Corstone-320 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-320 device: ARM::SSE-320-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U85.clayer.yml | With Ethos-U85 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,14 +51,14 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-320 FVP without Ethos-U or with Ethos-U85 +| fvp_config.txt | Corstone-320 FVP without or with an Ethos-U85-256 ### Python Requirements diff --git a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src +++ b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h index 3a68938f..19e2c883 100644 --- a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h +++ b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -64,14 +64,8 @@ /* ARM UART Controller CMSDK */ #ifdef RTE_USART0 #define UART0_CMSDK_S -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP; -#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S_TMP -#else #define UART0_CMSDK_DEV UART0_CMSDK_DEV_S #endif -#endif #ifdef RTE_USART1 #define UART1_CMSDK_S #define UART1_CMSDK_DEV UART1_CMSDK_DEV_S diff --git a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src +++ b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src +++ b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/example/FVP_Video/board/Corstone-320/regions_SSE-320.h b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h similarity index 100% rename from example/FVP_Video/board/Corstone-320/regions_SSE-320.h rename to example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/example/FVP_Video/board/Corstone-320/sse320_memmap_ns.h b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h similarity index 100% rename from example/FVP_Video/board/Corstone-320/sse320_memmap_ns.h rename to example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h diff --git a/example/FVP_Video/board/Corstone-320/sse320_memmap_s.h b/example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h similarity index 100% rename from example/FVP_Video/board/Corstone-320/sse320_memmap_s.h rename to example/FVP_Video/board/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h diff --git a/example/FVP_Video/board/Corstone-320/ethos_setup.c b/example/FVP_Video/board/Corstone-320/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/example/FVP_Video/board/Corstone-320/ethos_setup.c +++ b/example/FVP_Video/board/Corstone-320/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/example/FVP_Video/board/Corstone-320/ethosu_dcache.c b/example/FVP_Video/board/Corstone-320/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/example/FVP_Video/board/Corstone-320/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/example/FVP_Video/board/Corstone-320/ethosu_os_rtos2.c b/example/FVP_Video/board/Corstone-320/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/example/FVP_Video/board/Corstone-320/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/example/FVP_Video/board/Corstone-320/fvp_config.txt b/example/FVP_Video/board/Corstone-320/fvp_config.txt index d40b2d89..1f010c81 100644 --- a/example/FVP_Video/board/Corstone-320/fvp_config.txt +++ b/example/FVP_Video/board/Corstone-320/fvp_config.txt @@ -1,6 +1,7 @@ # Parameters: # instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] #------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.extra_args="--fast" # (string, init-time) default = '' : To activate fast processing mode, which significantly improves the performance of the model, set this parameter to "--fast". In fast mode, NPU performance counters are not representative of counters on real hardware. We recommend you do not use any other value without instructions from Arm Technical Support. mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] mps4_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr mps4_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected diff --git a/example/FVP_Video/board/Corstone-320/main.c b/example/FVP_Video/board/Corstone-320/main.c index 6d2b31ac..302d89f2 100644 --- a/example/FVP_Video/board/Corstone-320/main.c +++ b/example/FVP_Video/board/Corstone-320/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,32 +14,13 @@ * 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 "RTE_Components.h" #include CMSIS_device_header #include "main.h" -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -#include "uart_cmsdk_drv.h" - -static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S_TMP = { - .base = 0x58203000 + 0x01100000, - .default_baudrate = 115200 -}; -static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S_TMP = { - .state = 0, - .system_clk = 0, - .baudrate = 0 -}; -struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP = { - &(UART0_CMSDK_DEV_CFG_S_TMP), - &(UART0_CMSDK_DEV_DATA_S_TMP) -}; -#endif - int main (void) { /* Initialize STDIO */ @@ -50,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/example/FVP_Video/board/Corstone-320/main.h b/example/FVP_Video/board/Corstone-320/main.h index 6e2048ee..2b576ad2 100644 --- a/example/FVP_Video/board/Corstone-320/main.h +++ b/example/FVP_Video/board/Corstone-320/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/example/FVP_Video/project/FVP_Video.cproject.yml b/example/FVP_Video/project/FVP_Video.cproject.yml index 93092494..f69dda80 100644 --- a/example/FVP_Video/project/FVP_Video.cproject.yml +++ b/example/FVP_Video/project/FVP_Video.cproject.yml @@ -4,7 +4,7 @@ project: # List the packs that define the project software components. packs: - - pack: ARM::CMSIS@>=6.0.0 + - pack: ARM::CMSIS@^6.0.0 - pack: ARM::CMSIS-RTX # List connections used to identify compatible software layers. diff --git a/layer/README.md b/layer/README.md index 11440431..1616e496 100644 --- a/layer/README.md +++ b/layer/README.md @@ -30,7 +30,7 @@ Each board folder contains a **README** with implementation details and multiple | Layer File | NPU Configuration | Description | |:-----------------------|:------------------|:-------------------------------------------| | `Board.clayer.yml` | None | Cortex-M system only, no Ethos-U NPU | -| `Board-U55.clayer.yml` | Ethos-U55 | Cortex-M system + Ethos-U55 NPU (256 MACs) | +| `Board-U55.clayer.yml` | Ethos-U55 | Cortex-M system + Ethos-U55 NPU | | `Board-U65.clayer.yml` | Ethos-U65 | Cortex-M system + Ethos-U65 NPU | | `Board-U85.clayer.yml` | Ethos-U85 | Cortex-M system + Ethos-U85 NPU | diff --git a/layer/base/Corstone-300/Board-U55.clayer.yml b/layer/base/Corstone-300/Board-U55.clayer.yml index cb29ad94..49721d65 100644 --- a/layer/base/Corstone-300/Board-U55.clayer.yml +++ b/layer/base/Corstone-300/Board-U55.clayer.yml @@ -13,16 +13,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 128 - CORSTONE300_FVP packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -45,13 +46,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 128 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/base/Corstone-300/Board-U65.clayer.yml b/layer/base/Corstone-300/Board-U65.clayer.yml index 66ddc773..80bccc05 100644 --- a/layer/base/Corstone-300/Board-U65.clayer.yml +++ b/layer/base/Corstone-300/Board-U65.clayer.yml @@ -13,16 +13,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 256 - CORSTONE300_FVP packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -45,13 +46,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/base/Corstone-300/Board.clayer.yml b/layer/base/Corstone-300/Board.clayer.yml index 4405ad34..643c1a0b 100644 --- a/layer/base/Corstone-300/Board.clayer.yml +++ b/layer/base/Corstone-300/Board.clayer.yml @@ -20,7 +20,7 @@ layer: packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -45,8 +45,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/base/Corstone-300/Corstone-300.h b/layer/base/Corstone-300/Corstone-300.h index 5b318df2..4abb85d3 100644 --- a/layer/base/Corstone-300/Corstone-300.h +++ b/layer/base/Corstone-300/Corstone-300.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025-2026 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_300_H_ #define CORSTONE_300_H_ diff --git a/layer/base/Corstone-300/README.md b/layer/base/Corstone-300/README.md index 86f91d54..3833465c 100644 --- a/layer/base/Corstone-300/README.md +++ b/layer/base/Corstone-300/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-300-FVP -## Board Layer for Corstone-300 FVP +## Board Layers for Corstone-300 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-300-FVP device: ARM::SSE-300-MPS3 ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -29,11 +39,12 @@ This layer works for: ### CMSIS-Driver Virtual I/O mapping -VIO driver interfaces with the `arm_vio.py` Python stub implementation which -stores and loads signal values. +The VIO driver stores and loads signal values in memory. ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-300 FVP without Ethos-U or with Ethos-U55/U65 +| fvp_config.txt | Corstone-300 FVP without Ethos-U +| fvp_config_u55.txt | Corstone-300 FVP with an Ethos-U55-128 +| fvp_config_u65.txt | Corstone-300 FVP with an Ethos-U65-256 diff --git a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src +++ b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src index 545300e9..7ac73375 100644 --- a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src +++ b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src +++ b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src +++ b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/base/Corstone-300/regions_SSE-300.h b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h similarity index 100% rename from layer/base/Corstone-300/regions_SSE-300.h rename to layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/base/Corstone-300/sse300_memmap_ns.h b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h similarity index 100% rename from layer/base/Corstone-300/sse300_memmap_ns.h rename to layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h diff --git a/layer/base/Corstone-300/sse300_memmap_s.h b/layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h similarity index 100% rename from layer/base/Corstone-300/sse300_memmap_s.h rename to layer/base/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h diff --git a/layer/base/Corstone-300/ethos_setup.c b/layer/base/Corstone-300/ethos_setup.c index f154c77b..d4033b3a 100644 --- a/layer/base/Corstone-300/ethos_setup.c +++ b/layer/base/Corstone-300/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,8 +54,9 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/base/Corstone-300/ethosu_dcache.c b/layer/base/Corstone-300/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/base/Corstone-300/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/base/Corstone-300/ethosu_os_rtos2.c b/layer/base/Corstone-300/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/base/Corstone-300/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/base/Corstone-300/fvp_config_u55.txt b/layer/base/Corstone-300/fvp_config_u55.txt new file mode 100644 index 00000000..cecdf1b9 --- /dev/null +++ b/layer/base/Corstone-300/fvp_config_u55.txt @@ -0,0 +1,16 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#------------------------------------------------------------------------------ +ethosu.num_macs=128 # (int , init-time) default = '0x100' : Number of 8x8 MACs performed per cycle (32, 64, 128, or 256). +mps3_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal1.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal1.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal2.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal2.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal5.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal5.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.uart0.out_file=- # (string, init-time) default = '' : Output file to hold data written by the UART (use '-' to send all output to stdout) +mps3_board.uart0.shutdown_on_eot=1 # (bool , init-time) default = '0' : Shutdown simulation when a EOT (ASCII 4) char is transmitted (useful for regression tests when semihosting is not available) +mps3_board.visualisation.disable-visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +#------------------------------------------------------------------------------ diff --git a/layer/base/Corstone-300/fvp_config_u65.txt b/layer/base/Corstone-300/fvp_config_u65.txt new file mode 100644 index 00000000..b7d885c7 --- /dev/null +++ b/layer/base/Corstone-300/fvp_config_u65.txt @@ -0,0 +1,16 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#------------------------------------------------------------------------------ +ethosu.num_macs=256 # (int , init-time) default = '0x100' : Number of 8x8 MACs performed per cycle (32, 64, 128, or 256). +mps3_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal1.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal1.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal2.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal2.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.telnetterminal5.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr +mps3_board.telnetterminal5.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected +mps3_board.uart0.out_file=- # (string, init-time) default = '' : Output file to hold data written by the UART (use '-' to send all output to stdout) +mps3_board.uart0.shutdown_on_eot=1 # (bool , init-time) default = '0' : Shutdown simulation when a EOT (ASCII 4) char is transmitted (useful for regression tests when semihosting is not available) +mps3_board.visualisation.disable-visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +#------------------------------------------------------------------------------ diff --git a/layer/base/Corstone-300/main.c b/layer/base/Corstone-300/main.c index 69b34855..009aec00 100644 --- a/layer/base/Corstone-300/main.c +++ b/layer/base/Corstone-300/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header diff --git a/layer/base/Corstone-300/main.h b/layer/base/Corstone-300/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/base/Corstone-300/main.h +++ b/layer/base/Corstone-300/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/base/Corstone-310/Board-U55.clayer.yml b/layer/base/Corstone-310/Board-U55.clayer.yml index 6589b335..116c19d2 100644 --- a/layer/base/Corstone-310/Board-U55.clayer.yml +++ b/layer/base/Corstone-310/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Base configuration of SSE-310 FVP with Ethos U55 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -13,15 +13,16 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -44,13 +45,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/base/Corstone-310/Board-U65.clayer.yml b/layer/base/Corstone-310/Board-U65.clayer.yml index d1227db2..a57fc774 100644 --- a/layer/base/Corstone-310/Board-U65.clayer.yml +++ b/layer/base/Corstone-310/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Base configuration of SSE-310 FVP with Ethos U65 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -13,15 +13,16 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -44,13 +45,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/base/Corstone-310/Board.clayer.yml b/layer/base/Corstone-310/Board.clayer.yml index f2a8b490..d31c194d 100644 --- a/layer/base/Corstone-310/Board.clayer.yml +++ b/layer/base/Corstone-310/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Base configuration of SSE-310 FVP for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -19,7 +19,7 @@ layer: packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -44,8 +44,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/base/Corstone-310/Corstone-310.h b/layer/base/Corstone-310/Corstone-310.h index 8f41a3b9..6755af28 100644 --- a/layer/base/Corstone-310/Corstone-310.h +++ b/layer/base/Corstone-310/Corstone-310.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2026 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_310_H_ #define CORSTONE_310_H_ diff --git a/layer/base/Corstone-310/README.md b/layer/base/Corstone-310/README.md index ba312896..feba9d19 100644 --- a/layer/base/Corstone-310/README.md +++ b/layer/base/Corstone-310/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-310 -## Board Layer for Corstone-310 FVP +## Board Layers for Corstone-310 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-310 device: ARM::SSE-310-MPS3_FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -29,8 +39,7 @@ This layer works for: ### CMSIS-Driver Virtual I/O mapping -VIO driver interfaces with the `arm_vio.py` Python stub implementation which -stores and loads signal values. +The VIO driver stores and loads signal values in memory. ### FVP Configuration File diff --git a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src index ac2c3c65..3c82dcb4 100644 --- a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src +++ b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -67,11 +67,8 @@ LR_ROM0 __ROM0_BASE __ROM0_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -101,8 +98,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src index e7ec9d02..cdbf0a94 100644 --- a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src +++ b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src @@ -78,6 +78,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -316,6 +322,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src index 3f8cf75b..1ad41354 100644 --- a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src +++ b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -314,8 +314,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -327,7 +326,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src index ea02d531..639d4295 100644 --- a/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src +++ b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -42,8 +42,6 @@ define memory mem with size = 4G; define region ROM3_region = []; #endif -define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_region; - #if __RAM0_SIZE > 0 define region RAM0_region = mem:[from __RAM0_BASE to (__RAM0_BASE+__RAM0_SIZE-1)]; #else @@ -68,8 +66,6 @@ define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_regio define region RAM3_region = []; #endif -define region RAM_region = RAM0_region | RAM1_region | RAM2_region | RAM3_region; - do not initialize { section .noinit }; initialize by copy { readwrite }; if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) @@ -80,15 +76,37 @@ if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) place at address mem:__ROM0_BASE { readonly section .intvec }; -if (!isempty(ROM_region)) +if (!isempty(ROM0_region)) { - place in ROM_region { readonly }; + place in ROM0_region { readonly }; } -if (!isempty(RAM_region)) +if (!isempty(RAM0_region)) { define block CSTACK with alignment = 8, size = __STACK_SIZE { }; define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; - place in RAM_region { readwrite, block CSTACK, block PROC_STACK, block HEAP }; + place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else + place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/base/Corstone-310/regions_SSE-310.h b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h similarity index 100% rename from layer/base/Corstone-310/regions_SSE-310.h rename to layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/base/Corstone-310/sse310_memmap_ns.h b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h similarity index 100% rename from layer/base/Corstone-310/sse310_memmap_ns.h rename to layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h diff --git a/layer/base/Corstone-310/sse310_memmap_s.h b/layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h similarity index 100% rename from layer/base/Corstone-310/sse310_memmap_s.h rename to layer/base/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h diff --git a/layer/base/Corstone-310/ethos_setup.c b/layer/base/Corstone-310/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/base/Corstone-310/ethos_setup.c +++ b/layer/base/Corstone-310/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/base/Corstone-310/ethosu_dcache.c b/layer/base/Corstone-310/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/base/Corstone-310/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/base/Corstone-310/ethosu_os_rtos2.c b/layer/base/Corstone-310/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/base/Corstone-310/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/base/Corstone-310/main.c b/layer/base/Corstone-310/main.c index 69b34855..009aec00 100644 --- a/layer/base/Corstone-310/main.c +++ b/layer/base/Corstone-310/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header diff --git a/layer/base/Corstone-310/main.h b/layer/base/Corstone-310/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/base/Corstone-310/main.h +++ b/layer/base/Corstone-310/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/base/Corstone-315/Board-U65.clayer.yml b/layer/base/Corstone-315/Board-U65.clayer.yml index c4f59590..24b0dda4 100644 --- a/layer/base/Corstone-315/Board-U65.clayer.yml +++ b/layer/base/Corstone-315/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Base configuration of SSE-315 FVP with Ethos U65 for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -13,15 +13,16 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-315.h\" - - ETHOSU_MACS: 256 packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -43,14 +44,18 @@ layer: - component: Device:Native Driver:Timeout - component: Device:Native Driver:UART - - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/base/Corstone-315/Board.clayer.yml b/layer/base/Corstone-315/Board.clayer.yml index 38057d26..61838f6d 100644 --- a/layer/base/Corstone-315/Board.clayer.yml +++ b/layer/base/Corstone-315/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Base configuration of SSE-315 FVP for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -19,7 +19,7 @@ layer: packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -44,8 +44,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/base/Corstone-315/README.md b/layer/base/Corstone-315/README.md index eb49bd2c..b95c3ef4 100644 --- a/layer/base/Corstone-315/README.md +++ b/layer/base/Corstone-315/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-315 -## Board Layer for Corstone-315 FVP +## Board Layers for Corstone-315 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-315 device: ARM::SSE-315-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -29,8 +38,7 @@ This layer works for: ### CMSIS-Driver Virtual I/O mapping -VIO driver interfaces with the `arm_vio.py` Python stub implementation which -stores and loads signal values. +The VIO driver stores and loads signal values in memory. ### FVP Configuration File diff --git a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src +++ b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src +++ b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src +++ b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src +++ b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/base/Corstone-315/regions_SSE-315.h b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h similarity index 100% rename from layer/base/Corstone-315/regions_SSE-315.h rename to layer/base/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/base/Corstone-315/sse315_memmap_ns.h b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h similarity index 100% rename from layer/base/Corstone-315/sse315_memmap_ns.h rename to layer/base/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h diff --git a/layer/base/Corstone-315/sse315_memmap_s.h b/layer/base/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h similarity index 100% rename from layer/base/Corstone-315/sse315_memmap_s.h rename to layer/base/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h diff --git a/layer/base/Corstone-315/ethos_setup.c b/layer/base/Corstone-315/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/base/Corstone-315/ethos_setup.c +++ b/layer/base/Corstone-315/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/base/Corstone-315/ethosu_dcache.c b/layer/base/Corstone-315/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/base/Corstone-315/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/base/Corstone-315/ethosu_os_rtos2.c b/layer/base/Corstone-315/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/base/Corstone-315/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/base/Corstone-315/main.c b/layer/base/Corstone-315/main.c index 69b34855..009aec00 100644 --- a/layer/base/Corstone-315/main.c +++ b/layer/base/Corstone-315/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header diff --git a/layer/base/Corstone-315/main.h b/layer/base/Corstone-315/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/base/Corstone-315/main.h +++ b/layer/base/Corstone-315/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/base/Corstone-320/Board-U85.clayer.yml b/layer/base/Corstone-320/Board-U85.clayer.yml index b275bcbf..69dff740 100644 --- a/layer/base/Corstone-320/Board-U85.clayer.yml +++ b/layer/base/Corstone-320/Board-U85.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U85 + description: Base configuration of SSE-320 FVP with Ethos U85 for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -13,17 +13,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-320.h\" - - ETHOSU_MACS: 256 - - UART0_BASE_S_TMP packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -45,13 +45,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/base/Corstone-320/Board.clayer.yml b/layer/base/Corstone-320/Board.clayer.yml index 0ec102c8..12f993ee 100644 --- a/layer/base/Corstone-320/Board.clayer.yml +++ b/layer/base/Corstone-320/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Base configuration of SSE-320 FVP for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -16,12 +16,11 @@ layer: define: - CMSIS_target_header: \"Corstone-320.h\" - - UART0_BASE_S_TMP packs: - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -45,8 +44,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/base/Corstone-320/Corstone-320.h b/layer/base/Corstone-320/Corstone-320.h index 259b18e4..62630a08 100644 --- a/layer/base/Corstone-320/Corstone-320.h +++ b/layer/base/Corstone-320/Corstone-320.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2026 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_320_H_ #define CORSTONE_320_H_ diff --git a/layer/base/Corstone-320/README.md b/layer/base/Corstone-320/README.md index aa3b8083..3cf78934 100644 --- a/layer/base/Corstone-320/README.md +++ b/layer/base/Corstone-320/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-320 -## Board Layer for Corstone-320 FVP +## Board Layers for Corstone-320 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-320 device: ARM::SSE-320-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U85.clayer.yml | With Ethos-U85 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -29,12 +38,10 @@ This layer works for: ### CMSIS-Driver Virtual I/O mapping -VIO driver interfaces with the `arm_vio.py` Python stub implementation which -stores and loads signal values. +The VIO driver stores and loads signal values in memory. ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-320 FVP without Ethos-U or with Ethos-U85 - +| fvp_config.txt | Corstone-320 FVP without or with an Ethos-U85-256 diff --git a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src +++ b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src +++ b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h index 3a68938f..19e2c883 100644 --- a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h +++ b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -64,14 +64,8 @@ /* ARM UART Controller CMSDK */ #ifdef RTE_USART0 #define UART0_CMSDK_S -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP; -#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S_TMP -#else #define UART0_CMSDK_DEV UART0_CMSDK_DEV_S #endif -#endif #ifdef RTE_USART1 #define UART1_CMSDK_S #define UART1_CMSDK_DEV UART1_CMSDK_DEV_S diff --git a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src +++ b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src +++ b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/base/Corstone-320/regions_SSE-320.h b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h similarity index 100% rename from layer/base/Corstone-320/regions_SSE-320.h rename to layer/base/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/base/Corstone-320/sse320_memmap_ns.h b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h similarity index 100% rename from layer/base/Corstone-320/sse320_memmap_ns.h rename to layer/base/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h diff --git a/layer/base/Corstone-320/sse320_memmap_s.h b/layer/base/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h similarity index 100% rename from layer/base/Corstone-320/sse320_memmap_s.h rename to layer/base/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h diff --git a/layer/base/Corstone-320/ethos_setup.c b/layer/base/Corstone-320/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/base/Corstone-320/ethos_setup.c +++ b/layer/base/Corstone-320/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/base/Corstone-320/ethosu_dcache.c b/layer/base/Corstone-320/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/base/Corstone-320/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/base/Corstone-320/ethosu_os_rtos2.c b/layer/base/Corstone-320/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/base/Corstone-320/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/base/Corstone-320/fvp_config.txt b/layer/base/Corstone-320/fvp_config.txt index 2c648d67..d0dd7a46 100644 --- a/layer/base/Corstone-320/fvp_config.txt +++ b/layer/base/Corstone-320/fvp_config.txt @@ -1,6 +1,7 @@ # Parameters: # instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] #------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.extra_args="--fast" # (string, init-time) default = '' : To activate fast processing mode, which significantly improves the performance of the model, set this parameter to "--fast". In fast mode, NPU performance counters are not representative of counters on real hardware. We recommend you do not use any other value without instructions from Arm Technical Support. mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] mps4_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr mps4_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected diff --git a/layer/base/Corstone-320/main.c b/layer/base/Corstone-320/main.c index 6d2b31ac..009aec00 100644 --- a/layer/base/Corstone-320/main.c +++ b/layer/base/Corstone-320/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,32 +14,13 @@ * 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 "RTE_Components.h" #include CMSIS_device_header #include "main.h" -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -#include "uart_cmsdk_drv.h" - -static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S_TMP = { - .base = 0x58203000 + 0x01100000, - .default_baudrate = 115200 -}; -static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S_TMP = { - .state = 0, - .system_clk = 0, - .baudrate = 0 -}; -struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP = { - &(UART0_CMSDK_DEV_CFG_S_TMP), - &(UART0_CMSDK_DEV_DATA_S_TMP) -}; -#endif - int main (void) { /* Initialize STDIO */ diff --git a/layer/base/Corstone-320/main.h b/layer/base/Corstone-320/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/base/Corstone-320/main.h +++ b/layer/base/Corstone-320/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/vStream/Corstone-300/Board-U55.clayer.yml b/layer/vStream/Corstone-300/Board-U55.clayer.yml index 47d528c6..17fca191 100644 --- a/layer/vStream/Corstone-300/Board-U55.clayer.yml +++ b/layer/vStream/Corstone-300/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 128 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 128 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/vStream/Corstone-300/Board-U65.clayer.yml b/layer/vStream/Corstone-300/Board-U65.clayer.yml index 142bf2e8..b4b8f19a 100644 --- a/layer/vStream/Corstone-300/Board-U65.clayer.yml +++ b/layer/vStream/Corstone-300/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-300 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -17,17 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-300.h\" - - ETHOSU_MACS: 256 - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,13 +55,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/vStream/Corstone-300/Board.clayer.yml b/layer/vStream/Corstone-300/Board.clayer.yml index bfab0681..7475d525 100644 --- a/layer/vStream/Corstone-300/Board.clayer.yml +++ b/layer/vStream/Corstone-300/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-300 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-300-FVP for-device: ARM::SSE-300-MPS3 @@ -23,9 +23,9 @@ layer: - CORSTONE300_FVP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 components: @@ -54,8 +54,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-300.h + - regions: RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/vStream/Corstone-300/README.md b/layer/vStream/Corstone-300/README.md index a5f90047..420e25bf 100644 --- a/layer/vStream/Corstone-300/README.md +++ b/layer/vStream/Corstone-300/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-300-FVP -## Board Layer for Corstone-300 FVP +## Board Layers for Corstone-300 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-300-FVP device: ARM::SSE-300-MPS3 ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src +++ b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src index 545300e9..7ac73375 100644 --- a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src +++ b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src +++ b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src +++ b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/vStream/Corstone-300/regions_SSE-300.h b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h similarity index 100% rename from layer/vStream/Corstone-300/regions_SSE-300.h rename to layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/regions_SSE-300.h diff --git a/layer/vStream/Corstone-300/sse300_memmap_ns.h b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h similarity index 100% rename from layer/vStream/Corstone-300/sse300_memmap_ns.h rename to layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_ns.h diff --git a/layer/vStream/Corstone-300/sse300_memmap_s.h b/layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h similarity index 100% rename from layer/vStream/Corstone-300/sse300_memmap_s.h rename to layer/vStream/Corstone-300/RTE/Device/SSE-300-MPS3/sse300_memmap_s.h diff --git a/layer/vStream/Corstone-300/ethos_setup.c b/layer/vStream/Corstone-300/ethos_setup.c index f154c77b..d4033b3a 100644 --- a/layer/vStream/Corstone-300/ethos_setup.c +++ b/layer/vStream/Corstone-300/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,8 +54,9 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/vStream/Corstone-300/ethosu_dcache.c b/layer/vStream/Corstone-300/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/vStream/Corstone-300/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/vStream/Corstone-300/ethosu_os_rtos2.c b/layer/vStream/Corstone-300/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/vStream/Corstone-300/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/vStream/Corstone-300/main.c b/layer/vStream/Corstone-300/main.c index 69b34855..302d89f2 100644 --- a/layer/vStream/Corstone-300/main.c +++ b/layer/vStream/Corstone-300/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/layer/vStream/Corstone-300/main.h b/layer/vStream/Corstone-300/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/vStream/Corstone-300/main.h +++ b/layer/vStream/Corstone-300/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/vStream/Corstone-310/Board-U55.clayer.yml b/layer/vStream/Corstone-310/Board-U55.clayer.yml index 0141566e..2d5d613f 100644 --- a/layer/vStream/Corstone-310/Board-U55.clayer.yml +++ b/layer/vStream/Corstone-310/Board-U55.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U55 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U55 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/vStream/Corstone-310/Board-U65.clayer.yml b/layer/vStream/Corstone-310/Board-U65.clayer.yml index 0b62c4fb..16db95d4 100644 --- a/layer/vStream/Corstone-310/Board-U65.clayer.yml +++ b/layer/vStream/Corstone-310/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-310 FVP for AI/ML with Ethos U65 for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-310.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/vStream/Corstone-310/Board.clayer.yml b/layer/vStream/Corstone-310/Board.clayer.yml index 00edcbd0..c8636bed 100644 --- a/layer/vStream/Corstone-310/Board.clayer.yml +++ b/layer/vStream/Corstone-310/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-310 FVP for AI/ML for-board: ARM::V2M-MPS3-SSE-310 for-device: ARM::SSE-310-MPS3_FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-310.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-310.h + - regions: RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/vStream/Corstone-310/README.md b/layer/vStream/Corstone-310/README.md index 551fdac5..cea338bd 100644 --- a/layer/vStream/Corstone-310/README.md +++ b/layer/vStream/Corstone-310/README.md @@ -1,20 +1,30 @@ # Board: Arm V2M-MPS3-SSE-310 -## Board Layer for Corstone-310 FVP +## Board Layers for Corstone-310 FVP -This layer works for: +These layers work for: ```yml board: ARM::V2M-MPS3-SSE-310 device: ARM::SSE-310-MPS3_FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U55.clayer.yml | With Ethos-U55 support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +52,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src index ac2c3c65..3c82dcb4 100644 --- a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src +++ b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -67,11 +67,8 @@ LR_ROM0 __ROM0_BASE __ROM0_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -101,8 +98,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src index e7ec9d02..cdbf0a94 100644 --- a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src +++ b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/clang_linker_script.ld.src @@ -78,6 +78,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -316,6 +322,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src index 3f8cf75b..1ad41354 100644 --- a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src +++ b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -314,8 +314,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -327,7 +326,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src index ea02d531..639d4295 100644 --- a/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src +++ b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -42,8 +42,6 @@ define memory mem with size = 4G; define region ROM3_region = []; #endif -define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_region; - #if __RAM0_SIZE > 0 define region RAM0_region = mem:[from __RAM0_BASE to (__RAM0_BASE+__RAM0_SIZE-1)]; #else @@ -68,8 +66,6 @@ define region ROM_region = ROM0_region | ROM1_region | ROM2_region | ROM3_regio define region RAM3_region = []; #endif -define region RAM_region = RAM0_region | RAM1_region | RAM2_region | RAM3_region; - do not initialize { section .noinit }; initialize by copy { readwrite }; if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) @@ -80,15 +76,37 @@ if (isdefinedsymbol(__USE_DLIB_PERTHREAD)) place at address mem:__ROM0_BASE { readonly section .intvec }; -if (!isempty(ROM_region)) +if (!isempty(ROM0_region)) { - place in ROM_region { readonly }; + place in ROM0_region { readonly }; } -if (!isempty(RAM_region)) +if (!isempty(RAM0_region)) { define block CSTACK with alignment = 8, size = __STACK_SIZE { }; define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; - place in RAM_region { readwrite, block CSTACK, block PROC_STACK, block HEAP }; + place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else + place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/vStream/Corstone-310/regions_SSE-310.h b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h similarity index 100% rename from layer/vStream/Corstone-310/regions_SSE-310.h rename to layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/regions_SSE-310.h diff --git a/layer/vStream/Corstone-310/sse310_memmap_ns.h b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h similarity index 100% rename from layer/vStream/Corstone-310/sse310_memmap_ns.h rename to layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_ns.h diff --git a/layer/vStream/Corstone-310/sse310_memmap_s.h b/layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h similarity index 100% rename from layer/vStream/Corstone-310/sse310_memmap_s.h rename to layer/vStream/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/sse310_memmap_s.h diff --git a/layer/vStream/Corstone-310/ethos_setup.c b/layer/vStream/Corstone-310/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/vStream/Corstone-310/ethos_setup.c +++ b/layer/vStream/Corstone-310/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/vStream/Corstone-310/ethosu_dcache.c b/layer/vStream/Corstone-310/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/vStream/Corstone-310/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/vStream/Corstone-310/ethosu_os_rtos2.c b/layer/vStream/Corstone-310/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/vStream/Corstone-310/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/vStream/Corstone-310/main.c b/layer/vStream/Corstone-310/main.c index 69b34855..302d89f2 100644 --- a/layer/vStream/Corstone-310/main.c +++ b/layer/vStream/Corstone-310/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/layer/vStream/Corstone-310/main.h b/layer/vStream/Corstone-310/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/vStream/Corstone-310/main.h +++ b/layer/vStream/Corstone-310/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/vStream/Corstone-315/Board-U65.clayer.yml b/layer/vStream/Corstone-315/Board-U65.clayer.yml index a4f57c54..4926cf82 100644 --- a/layer/vStream/Corstone-315/Board-U65.clayer.yml +++ b/layer/vStream/Corstone-315/Board-U65.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U65 + description: Configuration of SSE-315 FVP for AI/ML with Ethos U65 for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -17,16 +17,17 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-315.h\" - - ETHOSU_MACS: 256 packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -52,14 +53,18 @@ layer: - component: Device:Native Driver:Timeout - component: Device:Native Driver:UART - - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/vStream/Corstone-315/Board.clayer.yml b/layer/vStream/Corstone-315/Board.clayer.yml index f9b1bcae..13622db5 100644 --- a/layer/vStream/Corstone-315/Board.clayer.yml +++ b/layer/vStream/Corstone-315/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-315 FVP for AI/ML for-board: ARM::SSE-315 for-device: ARM::SSE-315-FVP @@ -22,9 +22,9 @@ layer: - CMSIS_target_header: \"Corstone-315.h\" packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 - pack: ARM::SSE_315_BSP@1.0.0 components: @@ -53,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-315.h + - regions: RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/vStream/Corstone-315/README.md b/layer/vStream/Corstone-315/README.md index 3c8dd2aa..f7a0c014 100644 --- a/layer/vStream/Corstone-315/README.md +++ b/layer/vStream/Corstone-315/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-315 -## Board Layer for Corstone-315 FVP +## Board Layers for Corstone-315 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-315 device: ARM::SSE-315-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U65.clayer.yml | With Ethos-U65 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,8 +51,8 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File diff --git a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src +++ b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src +++ b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src +++ b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src +++ b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/vStream/Corstone-315/regions_SSE-315.h b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h similarity index 100% rename from layer/vStream/Corstone-315/regions_SSE-315.h rename to layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/regions_SSE-315.h diff --git a/layer/vStream/Corstone-315/sse315_memmap_ns.h b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h similarity index 100% rename from layer/vStream/Corstone-315/sse315_memmap_ns.h rename to layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_ns.h diff --git a/layer/vStream/Corstone-315/sse315_memmap_s.h b/layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h similarity index 100% rename from layer/vStream/Corstone-315/sse315_memmap_s.h rename to layer/vStream/Corstone-315/RTE/Device/SSE-315-FVP/sse315_memmap_s.h diff --git a/layer/vStream/Corstone-315/ethos_setup.c b/layer/vStream/Corstone-315/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/vStream/Corstone-315/ethos_setup.c +++ b/layer/vStream/Corstone-315/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/vStream/Corstone-315/ethosu_dcache.c b/layer/vStream/Corstone-315/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/vStream/Corstone-315/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/vStream/Corstone-315/ethosu_os_rtos2.c b/layer/vStream/Corstone-315/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/vStream/Corstone-315/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/vStream/Corstone-315/main.c b/layer/vStream/Corstone-315/main.c index 69b34855..302d89f2 100644 --- a/layer/vStream/Corstone-315/main.c +++ b/layer/vStream/Corstone-315/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 "RTE_Components.h" #include CMSIS_device_header @@ -31,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/layer/vStream/Corstone-315/main.h b/layer/vStream/Corstone-315/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/vStream/Corstone-315/main.h +++ b/layer/vStream/Corstone-315/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__ diff --git a/layer/vStream/Corstone-320/Board-U85.clayer.yml b/layer/vStream/Corstone-320/Board-U85.clayer.yml index 0426a2c1..2fe6528f 100644 --- a/layer/vStream/Corstone-320/Board-U85.clayer.yml +++ b/layer/vStream/Corstone-320/Board-U85.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML with Ethos U85 + description: Configuration of SSE-320 FVP for AI/ML with Ethos U85 for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -17,18 +17,18 @@ layer: - STDOUT - STDERR - Heap: 98304 + consumes: + - CMSIS-RTOS2 define: - CMSIS_target_header: \"Corstone-320.h\" - - ETHOSU_MACS: 256 - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - - pack: ARM::CMSIS-Ethos-U@^1.0.0-0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::CMSIS-Ethos-U@^1.0.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,13 +54,17 @@ layer: - component: Device:Native Driver:UART - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + define: + - ETHOSU_MACS: 256 groups: - group: Board files: - - file: ./main.c - - file: ./main.h - - file: ./ethos_setup.c + - file: main.c + - file: main.h + - file: ethos_setup.c + - file: ethosu_os_rtos2.c + - file: ethosu_dcache.c linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/vStream/Corstone-320/Board.clayer.yml b/layer/vStream/Corstone-320/Board.clayer.yml index ccf943ba..4540ba1d 100644 --- a/layer/vStream/Corstone-320/Board.clayer.yml +++ b/layer/vStream/Corstone-320/Board.clayer.yml @@ -1,6 +1,6 @@ layer: type: Board - description: Board setup for AI/ML + description: Configuration of SSE-320 FVP for AI/ML for-board: ARM::SSE-320 for-device: ARM::SSE-320-FVP @@ -20,13 +20,12 @@ layer: define: - CMSIS_target_header: \"Corstone-320.h\" - - UART0_BASE_S_TMP packs: - - pack: ARM::CMSIS - - pack: ARM::CMSIS-Compiler@^2.2.0 - pack: ARM::AVH_FVP - - pack: ARM::SSE_320_BSP@1.1.0 + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.3.0 + - pack: ARM::SSE_320_BSP@^2.0.0 components: - component: CMSIS:CORE @@ -54,8 +53,8 @@ layer: groups: - group: Board files: - - file: ./main.c - - file: ./main.h + - file: main.c + - file: main.h linker: - - regions: ./regions_SSE-320.h + - regions: RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/vStream/Corstone-320/Corstone-320.h b/layer/vStream/Corstone-320/Corstone-320.h index 456d842d..f41a3813 100644 --- a/layer/vStream/Corstone-320/Corstone-320.h +++ b/layer/vStream/Corstone-320/Corstone-320.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 CORSTONE_320_H_ #define CORSTONE_320_H_ diff --git a/layer/vStream/Corstone-320/README.md b/layer/vStream/Corstone-320/README.md index aa8836fe..c31a72f1 100644 --- a/layer/vStream/Corstone-320/README.md +++ b/layer/vStream/Corstone-320/README.md @@ -1,20 +1,29 @@ # Board: Arm SSE-320 -## Board Layer for Corstone-320 FVP +## Board Layers for Corstone-320 FVP -This layer works for: +These layers work for: ```yml board: ARM::SSE-320 device: ARM::SSE-320-FVP ``` +Select one layer matching the application's NPU requirements: + +| Layer file | Use in Application +|:---------------------|:------------------------ +| Board.clayer.yml | Without Ethos-U support +| Board-U85.clayer.yml | With Ethos-U85 support + +Use the corresponding FVP configuration file listed below. + ### System Configuration | System Component | Setting |:------------------------|:---------------------------------- -| Heap | 96 kB (configured in linker file) -| Stack (MSP) | 32 kB (configured in linker file) +| Heap | 96 kB (configured in regions header) +| Stack (MSP) | 4 kB (configured in regions header) ### STDIO mapping @@ -42,14 +51,14 @@ stores and loads signal values. |:-----------------------|:---------------------------------------------------- | Driver_vStreamAudioIn | 16-bit PCM audio, 16000 samples/second | Driver_vStreamAudioOut | 16-bit PCM audio, 16000 samples/second -| Driver_vStreamVideoIn | RGB888 video, resolution 1280 x 720 (W x H) -| Driver_vStreamVideoOut | RGB888 video, resolution 480 x 800 (W x H) +| Driver_vStreamVideoIn | RGB888 video, resolution 640 x 480 (W x H) +| Driver_vStreamVideoOut | RGB888 video, resolution 640 x 480 (W x H) ### FVP Configuration File | File | Description |:-------------------|:------------- -| fvp_config.txt | Corstone-320 FVP without Ethos-U or with Ethos-U85 +| fvp_config.txt | Corstone-320 FVP without or with an Ethos-U85-256 ### Python Requirements diff --git a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src index 233a6de6..3576f334 100644 --- a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src +++ b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -73,11 +73,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __RAM1_SIZE > 0 RW_RAM1 __RAM1_BASE __RAM1_SIZE { - ; Ethos-U Cache Area - *.o (*ethos_cache_buf) - - ; NN Activation Tensor (activation buffer / tensor arena) - *.o (*activation_buf) + ; Ethos-U writable area + *.o (ethos_arena) .ANY (+RW +ZI) } @@ -99,8 +96,8 @@ LR_ROM1 __ROM1_BASE __ROM1_SIZE { #if __ROM2_SIZE > 0 LR_ROM2 __ROM2_BASE __ROM2_SIZE { ER_ROM2 +0 __ROM2_SIZE { - ; NN Model Binary Representation - *.o (nn_model) + ; Ethos-U model, command stream and constants + *.o (ethos_model) .ANY (+RO +XO) } diff --git a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src index 6b12265a..9071fba8 100644 --- a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src +++ b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/clang_linker_script.ld.src @@ -79,6 +79,12 @@ PHDRS ram PT_LOAD; ram_init PT_LOAD; tls PT_TLS; +#if __RAM1_SIZE > 0 + ethos_ram PT_LOAD; +#endif +#if __ROM2_SIZE > 0 + ethos_model PT_LOAD; +#endif } SECTIONS @@ -317,6 +323,20 @@ SECTIONS } >RAM0 :ram #endif + /* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + .ethos_arena (NOLOAD) : ALIGN(32) { + *(ethos_arena) + } >RAM1 AT>RAM1 :ethos_ram +#endif + + /* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + .ethos_model : ALIGN(32) { + *(ethos_model) + } >ROM2 AT>ROM2 :ethos_model +#endif + /* Throw away C++ exception handling information */ /* diff --git a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h index 3a68938f..19e2c883 100644 --- a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h +++ b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -64,14 +64,8 @@ /* ARM UART Controller CMSDK */ #ifdef RTE_USART0 #define UART0_CMSDK_S -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -extern struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP; -#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S_TMP -#else #define UART0_CMSDK_DEV UART0_CMSDK_DEV_S #endif -#endif #ifdef RTE_USART1 #define UART1_CMSDK_S #define UART1_CMSDK_DEV UART1_CMSDK_DEV_S diff --git a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src index 2e2ef6f1..9f6f1a0b 100644 --- a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src +++ b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -318,8 +318,7 @@ SECTIONS .cache (NOLOAD): { . = ALIGN(32); - *(*ethos_cache_buf) /* Ethos-U Cache Area */ - *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + *(ethos_arena) /* Ethos-U writable area */ } > RAM1 /* Initialized buffers in fast access RAM */ @@ -331,7 +330,7 @@ SECTIONS .rom2 : { - *(*nn_model) /* NN Model Binary Representation */ + *(ethos_model) /* Ethos-U model, command stream and constants */ } > ROM2 .rom3 : diff --git a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src index 1a3548b4..7d05a925 100644 --- a/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src +++ b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -87,5 +87,26 @@ if (!isempty(RAM0_region)) define block PROC_STACK with alignment = 8, size = 0 { }; define block HEAP with alignment = 8, size = __HEAP_SIZE { }; place in RAM0_region { readwrite, block PROC_STACK, block HEAP }; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + /* Reserve the stack seal immediately above the stack. */ + define block STACKSEAL with alignment = 8, size = 8 { }; + define block CSTACK_WITH_SEAL with fixed order { block CSTACK, block STACKSEAL }; + place at end of RAM0_region { block CSTACK_WITH_SEAL }; +#else place at end of RAM0_region { block CSTACK }; +#endif } + +/* Ethos-U writable area */ +#if __RAM1_SIZE > 0 + do not initialize { section ethos_arena }; + define block ETHOS_ARENA with alignment = 32 + { section ethos_arena }; + place in RAM1_region { block ETHOS_ARENA }; +#endif + +/* Ethos-U model, command stream and constants */ +#if __ROM2_SIZE > 0 + define block ETHOS_MODEL with alignment = 32 { readonly section ethos_model }; + place in ROM2_region { block ETHOS_MODEL }; +#endif diff --git a/layer/vStream/Corstone-320/regions_SSE-320.h b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h similarity index 100% rename from layer/vStream/Corstone-320/regions_SSE-320.h rename to layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/regions_SSE-320.h diff --git a/layer/vStream/Corstone-320/sse320_memmap_ns.h b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h similarity index 100% rename from layer/vStream/Corstone-320/sse320_memmap_ns.h rename to layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_ns.h diff --git a/layer/vStream/Corstone-320/sse320_memmap_s.h b/layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h similarity index 100% rename from layer/vStream/Corstone-320/sse320_memmap_s.h rename to layer/vStream/Corstone-320/RTE/Device/SSE-320-FVP/sse320_memmap_s.h diff --git a/layer/vStream/Corstone-320/ethos_setup.c b/layer/vStream/Corstone-320/ethos_setup.c index ca26dfac..4787ebb8 100644 --- a/layer/vStream/Corstone-320/ethos_setup.c +++ b/layer/vStream/Corstone-320/ethos_setup.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2025-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ * 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 @@ -26,18 +26,18 @@ #if defined(ETHOSU65) || defined(ETHOSU85) /* Define Ethos-U NPU cache buffer size */ -#ifndef ETHOS_CACHE_BUF_SIZE -#define ETHOS_CACHE_BUF_SIZE 393216 +#ifndef ETHOS_CACHE_SIZE +#define ETHOS_CACHE_SIZE 0 #endif /* Define Ethos-U cache buffer alignment */ -#ifndef ETHOS_CACHE_BUF_ALIGNMENT -#define ETHOS_CACHE_BUF_ALIGNMENT 32 +#ifndef ETHOS_CACHE_ALIGNMENT +#define ETHOS_CACHE_ALIGNMENT 32 #endif /* Define Ethos-U NPU cache buffer attributes */ -#ifndef ETHOS_CACHE_BUF_ATTRIBUTES -#define ETHOS_CACHE_BUF_ATTRIBUTES __attribute__((section("ethos_cache_buf"), aligned(ETHOS_CACHE_BUF_ALIGNMENT))) +#ifndef ETHOS_CACHE_ATTRIBUTES +#define ETHOS_CACHE_ATTRIBUTES __attribute__((section("ethos_cache"), aligned(ETHOS_CACHE_ALIGNMENT))) #endif #endif @@ -54,14 +54,15 @@ /* Ethos NPU driver instance. */ static struct ethosu_driver EthosDriver; -#if defined(ETHOSU65) || defined(ETHOSU85) -static uint8_t ethos_cache[ETHOS_CACHE_BUF_SIZE] ETHOS_CACHE_BUF_ATTRIBUTES; +#if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) +/* Ethos-U NPU cache buffer */ +static uint8_t ethos_cache_buf[ETHOS_CACHE_SIZE] ETHOS_CACHE_ATTRIBUTES; #endif /* Ethos NPU interrupt handler. */ -void NPU0_Handler(void) { +void NPU0_Handler (void) { ethosu_irq_handler(&EthosDriver); } @@ -76,9 +77,9 @@ void ethos_setup (void) { /* Initialize Ethos-U NPU driver. */ rval = ethosu_init(&EthosDriver, /* Ethos-U device driver */ ethos_base_addr, /* Ethos-U base address */ - #if defined(ETHOSU65) || defined(ETHOSU85) - ethos_cache, /* Cache memory pointer */ - sizeof(ethos_cache), /* Cache memory size */ + #if (defined(ETHOSU65) || defined(ETHOSU85)) && (ETHOS_CACHE_SIZE > 0) + ethos_cache_buf, /* Cache memory pointer */ + sizeof(ethos_cache_buf), /* Cache memory size */ #else 0, /* Cache memory pointer */ 0, /* Cache memory size */ diff --git a/layer/vStream/Corstone-320/ethosu_dcache.c b/layer/vStream/Corstone-320/ethosu_dcache.c new file mode 100644 index 00000000..015a9d1f --- /dev/null +++ b/layer/vStream/Corstone-320/ethosu_dcache.c @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 + +#include "ethosu_driver.h" + +/** + \brief Cleans data-cache contents associated with buffers accessed by the NPU. + + Ensures that CPU writes to cacheable buffers are committed to memory before + the NPU starts accessing them. Non-cacheable buffers require no cache clean, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_flush_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Flush data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // CleanDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} + +/** + \brief Invalidates data-cache contents associated with buffers accessed by the NPU. + + Ensures that subsequent CPU reads observe data written by the NPU. Dirty + cache lines may be cleaned before invalidation to preserve pending CPU + writes. For non-cacheable buffers, no cache invalidation is required, + but the function ensures that all preceding memory accesses have completed + before it returns. + + \param[in] base_addr Array of buffer base addresses. + \param[in] base_addr_size Array containing the size, in bytes, of each buffer. + \param[in] num_base_addr Number of entries in the address and size arrays. +*/ +void ethosu_invalidate_dcache(const uint64_t *base_addr, const size_t *base_addr_size, int num_base_addr) { + + for (int i = 0; i < num_base_addr; i++) { + if ((base_addr[i] & 0x1F) != 0) { + /* Base address must be cache line aligned (32 bytes) */ + // ... + return; + } + + /* Invalidate data-cache for current buffer */ + // ... + // 32-bit system must cast base_addr to uint32_t* to avoid sign expansion + // InvalidateDCache((uint32_t *)(uint32_t)base_addr[i], base_addr_size[i]); + } +} diff --git a/layer/vStream/Corstone-320/ethosu_os_rtos2.c b/layer/vStream/Corstone-320/ethosu_os_rtos2.c new file mode 100644 index 00000000..fdab39b9 --- /dev/null +++ b/layer/vStream/Corstone-320/ethosu_os_rtos2.c @@ -0,0 +1,141 @@ +/* + * Copyright 2026 Arm Limited and/or its affiliates. + * + * 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 "ethosu_driver.h" +#include "cmsis_os2.h" + +/* Maximum number of Ethos-U instances. */ +/* Used as maximum semaphore count in ethosu_semaphore_create. */ +#ifndef ETHOSU_MAX_INSTANCES +#define ETHOSU_MAX_INSTANCES 2 +#endif + +/** + \brief Create a mutex object. + \return Pointer to a mutex object. +*/ +void *ethosu_mutex_create(void) { + osMutexId_t mutex_id = osMutexNew(NULL); + return (void *) mutex_id; +} + +/** + \brief Destroy a mutex object. + \param[in] mutex mutex object. +*/ +void ethosu_mutex_destroy(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osMutexDelete(mutex_id); +} + +/** + \brief Lock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_lock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexAcquire(mutex_id, osWaitForever); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Unlock a mutex. + \param[in] mutex mutex object. + \return 0 on success, else negative error codes +*/ +int ethosu_mutex_unlock(void *mutex) { + osMutexId_t mutex_id = (osMutexId_t) mutex; + osStatus_t status; + int rval; + + status = osMutexRelease(mutex_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Create a semaphore object. + \return Pointer to a semaphore object. +*/ +void *ethosu_semaphore_create(void) { + osSemaphoreId_t sem_id; + + sem_id = osSemaphoreNew(ETHOSU_MAX_INSTANCES, 0U, NULL); + return (void *) sem_id; +} + +/** + \brief Destroy a semaphore object. + \param[in] sem semaphore object. +*/ +void ethosu_semaphore_destroy(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osSemaphoreDelete(sem_id); +} + +/** + \brief Take a semaphore object with timeout. + \param[in] sem semaphore object. + \param[in] timeout timeout value in ticks. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_take(void *sem, uint64_t timeout) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreAcquire(sem_id, timeout); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} + +/** + \brief Give a semaphore object. + \param[in] sem semaphore object. + \return 0 on success, else negative error codes +*/ +int ethosu_semaphore_give(void *sem) { + osSemaphoreId_t sem_id = (osSemaphoreId_t) sem; + osStatus_t status; + int rval; + + status = osSemaphoreRelease(sem_id); + if (status == osOK) { + rval = 0; + } else { + rval = -1; + } + return rval; +} diff --git a/layer/vStream/Corstone-320/fvp_config.txt b/layer/vStream/Corstone-320/fvp_config.txt index d40b2d89..1f010c81 100644 --- a/layer/vStream/Corstone-320/fvp_config.txt +++ b/layer/vStream/Corstone-320/fvp_config.txt @@ -1,6 +1,7 @@ # Parameters: # instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] #------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.extra_args="--fast" # (string, init-time) default = '' : To activate fast processing mode, which significantly improves the performance of the model, set this parameter to "--fast". In fast mode, NPU performance counters are not representative of counters on real hardware. We recommend you do not use any other value without instructions from Arm Technical Support. mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] mps4_board.telnetterminal0.quiet=1 # (bool , init-time) default = '0' : Avoid output on stdout/stderr mps4_board.telnetterminal0.start_telnet=0 # (bool , init-time) default = '1' : Start telnet if nothing connected diff --git a/layer/vStream/Corstone-320/main.c b/layer/vStream/Corstone-320/main.c index 6d2b31ac..302d89f2 100644 --- a/layer/vStream/Corstone-320/main.c +++ b/layer/vStream/Corstone-320/main.c @@ -1,5 +1,5 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. +/* + * Copyright 2024-2026 Arm Limited and/or its affiliates. * * SPDX-License-Identifier: Apache-2.0 * @@ -14,32 +14,13 @@ * 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 "RTE_Components.h" #include CMSIS_device_header #include "main.h" -#ifdef UART0_BASE_S_TMP -/* Workaround for UART0 CMSDK base address mismatch */ -#include "uart_cmsdk_drv.h" - -static const struct uart_cmsdk_dev_cfg_t UART0_CMSDK_DEV_CFG_S_TMP = { - .base = 0x58203000 + 0x01100000, - .default_baudrate = 115200 -}; -static struct uart_cmsdk_dev_data_t UART0_CMSDK_DEV_DATA_S_TMP = { - .state = 0, - .system_clk = 0, - .baudrate = 0 -}; -struct uart_cmsdk_dev_t UART0_CMSDK_DEV_S_TMP = { - &(UART0_CMSDK_DEV_CFG_S_TMP), - &(UART0_CMSDK_DEV_DATA_S_TMP) -}; -#endif - int main (void) { /* Initialize STDIO */ @@ -50,5 +31,14 @@ int main (void) { ethos_setup(); #endif + /* Set VSI interrupt priorities */ + NVIC_SetPriority(ARM_VSI0_IRQn, 7U); + NVIC_SetPriority(ARM_VSI1_IRQn, 7U); + NVIC_SetPriority(ARM_VSI2_IRQn, 7U); + NVIC_SetPriority(ARM_VSI3_IRQn, 7U); + NVIC_SetPriority(ARM_VSI4_IRQn, 7U); + NVIC_SetPriority(ARM_VSI5_IRQn, 7U); + NVIC_SetPriority(ARM_VSI6_IRQn, 7U); + return (app_main()); } diff --git a/layer/vStream/Corstone-320/main.h b/layer/vStream/Corstone-320/main.h index 6e2048ee..2b576ad2 100644 --- a/layer/vStream/Corstone-320/main.h +++ b/layer/vStream/Corstone-320/main.h @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2020-2025 Arm Limited (or its affiliates). - * All rights reserved. +/* + * Copyright 2020-2026 Arm Limited and/or its affiliates. + * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -14,7 +14,7 @@ * 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 MAIN_H__ #define MAIN_H__