diff --git a/ARM.AVH_FVP.pdsc b/ARM.AVH_FVP.pdsc index b71fad6..a7426f6 100644 --- a/ARM.AVH_FVP.pdsc +++ b/ARM.AVH_FVP.pdsc @@ -30,6 +30,31 @@ + + + Requirements for Corstone-310 FVP + + + + + + Requirements for Corstone-310 FVP + + + + + + Requirements for Corstone-315 FVP + + + + + + Requirements for Corstone-320 FVP + + + + @@ -110,4 +135,20 @@ + + + + + + + + + + + + + + + + diff --git a/board/Corstone-300/Board-U55.clayer.yml b/board/Corstone-300/Board-U55.clayer.yml new file mode 100644 index 0000000..cb372e0 --- /dev/null +++ b/board/Corstone-300/Board-U55.clayer.yml @@ -0,0 +1,65 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U55 + for-board: ARM::V2M-MPS3-SSE-300-FVP + for-device: ARM::SSE-300-MPS3 + + connections: + - connect: Corstone-300-U55 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-300.h\" + - ETHOSU55 + - CORSTONE300_FVP + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-300.h diff --git a/board/Corstone-300/Board-U65.clayer.yml b/board/Corstone-300/Board-U65.clayer.yml new file mode 100644 index 0000000..bd39b8d --- /dev/null +++ b/board/Corstone-300/Board-U65.clayer.yml @@ -0,0 +1,65 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U65 + for-board: ARM::V2M-MPS3-SSE-300-FVP + for-device: ARM::SSE-300-MPS3 + + connections: + - connect: Corstone-300-U65 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-300.h\" + - ETHOSU65 + - CORSTONE300_FVP + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-300.h diff --git a/board/Corstone-300/Board.clayer.yml b/board/Corstone-300/Board.clayer.yml new file mode 100644 index 0000000..6046fc0 --- /dev/null +++ b/board/Corstone-300/Board.clayer.yml @@ -0,0 +1,60 @@ +layer: + type: Board + description: Board setup for AI/ML + for-board: ARM::V2M-MPS3-SSE-300-FVP + for-device: ARM::SSE-300-MPS3 + + connections: + - connect: Corstone-300 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-300.h\" + - CORSTONE300_FVP + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_300_BSP@1.5.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-300.h diff --git a/board/Corstone-300/Corstone-300.h b/board/Corstone-300/Corstone-300.h new file mode 100644 index 0000000..3a5dde4 --- /dev/null +++ b/board/Corstone-300/Corstone-300.h @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef CORSTONE_300_H_ +#define CORSTONE_300_H_ + +#include "Driver_USART.h" +#include "cmsis_vstream.h" + +// CMSIS Driver instances of Board peripherals +#define CMSIS_DRIVER_USART 0 // CMSIS Driver USART instance number + +// Retarget stdio to CMSIS UART +#define RETARGET_STDIO_UART 0 + +// CMSIS Drivers +extern ARM_DRIVER_USART Driver_USART0; /* Serial */ +extern vStreamDriver_t Driver_vStreamAudioIn; /* Audio In Stream */ +extern vStreamDriver_t Driver_vStreamAudioOut; /* Audio Out Stream */ +extern vStreamDriver_t Driver_vStreamVideoIn; /* Video In Stream */ +extern vStreamDriver_t Driver_vStreamVideoOut; /* Video Out Stream */ + +#ifdef CMSIS_shield_header +#include CMSIS_shield_header +#endif + +#endif /* CORSTONE_300_H_ */ diff --git a/board/Corstone-300/README.md b/board/Corstone-300/README.md new file mode 100644 index 0000000..a47465c --- /dev/null +++ b/board/Corstone-300/README.md @@ -0,0 +1,35 @@ +# Board: Arm V2M-MPS3-SSE-300-FVP + +## Board Layer for Corstone-300 FVP + +Device: SSE-300-MPS3 + +### System Configuration + +| System Component | Setting +|:------------------------|:---------------------------------- +| Heap | 768 kB (configured in linker file) +| Stack (MSP) | 32 kB (configured in linker file) + +### STDIO mapping + +**STDIO** is routed to terminal via **UART0** peripheral + +### CMSIS-Driver mapping + +| CMSIS-Driver | Peripheral | Connection +|:-----------------------|:-----------|:---------------------- +| Driver_USART0 | UART0 | STDOUT, STDERR +| Driver_vStreamAudioIn | VSI0 | CMSIS_VSTREAM_AUDIO_IN +| Driver_vStreamAudioOut | VSI1 | CMSIS_VSTREAM_AUDIO_OUT +| Driver_vStreamVideoIn | VSI4 | CMSIS_VSTREAM_VIDEO_IN +| Driver_vStreamVideoOut | VSI6 | CMSIS_VSTREAM_VIDEO_OUT + +### CMSIS-Driver vStream configuration + +| Driver | Stream Format Description +|:-----------------------|:---------------------------------------------------- +| 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) diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h new file mode 100644 index 0000000..fd1d7d0 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 new file mode 100644 index 0000000..a4e79fe --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h new file mode 100644 index 0000000..da9aa7e --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 new file mode 100644 index 0000000..b59bf69 --- /dev/null +++ b/board/Corstone-300/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src b/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src new file mode 100644 index 0000000..233a6de --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/ac6_linker_script.sct.src @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE 8 +#else +#define __STACKSEAL_SIZE 0 +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + + ER_ROM0 __ROM0_BASE __ROM0_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + } + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) { + *(Veneer$$CMSE) + } +#endif +} + +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + + ER_ROM1 __ROM1_BASE __ROM1_SIZE { + *(+RO +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) { + *.o(.bss.noinit) + *.o(.bss.noinit.*) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#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) + + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + ; NN Model Binary Representation + *.o (nn_model) + + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h b/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h new file mode 100644 index 0000000..0e9746a --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S + +/* I2C_SBCon */ +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S + +/* I2S */ +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S + +/* ARM UART Controller PL011 */ +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S + +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S + +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S + +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S + +/** System Counter Armv8-M */ +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u + +/* System timer */ +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) + +/* CMSDK GPIO driver structures */ +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S + +/* System Watchdogs */ +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S + +/* ARM MPC SIE 300 driver structures */ +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S + +/* ARM PPC driver structures */ +#define PPC_SSE300_MAIN0_S +#define PPC_SSE300_MAIN0_DEV PPC_SSE300_MAIN0_DEV_S +#define PPC_SSE300_MAIN_EXP0_S +#define PPC_SSE300_MAIN_EXP0_DEV PPC_SSE300_MAIN_EXP0_DEV_S +#define PPC_SSE300_MAIN_EXP1_S +#define PPC_SSE300_MAIN_EXP1_DEV PPC_SSE300_MAIN_EXP1_DEV_S +#define PPC_SSE300_MAIN_EXP2_S +#define PPC_SSE300_MAIN_EXP2_DEV PPC_SSE300_MAIN_EXP2_DEV_S +#define PPC_SSE300_MAIN_EXP3_S +#define PPC_SSE300_MAIN_EXP3_DEV PPC_SSE300_MAIN_EXP3_DEV_S +#define PPC_SSE300_PERIPH0_S +#define PPC_SSE300_PERIPH0_DEV PPC_SSE300_PERIPH0_DEV_S +#define PPC_SSE300_PERIPH1_S +#define PPC_SSE300_PERIPH1_DEV PPC_SSE300_PERIPH1_DEV_S +#define PPC_SSE300_PERIPH_EXP0_S +#define PPC_SSE300_PERIPH_EXP0_DEV PPC_SSE300_PERIPH_EXP0_DEV_S +#define PPC_SSE300_PERIPH_EXP1_S +#define PPC_SSE300_PERIPH_EXP1_DEV PPC_SSE300_PERIPH_EXP1_DEV_S +#define PPC_SSE300_PERIPH_EXP2_S +#define PPC_SSE300_PERIPH_EXP2_DEV PPC_SSE300_PERIPH_EXP2_DEV_S +#define PPC_SSE300_PERIPH_EXP3_S +#define PPC_SSE300_PERIPH_EXP3_DEV PPC_SSE300_PERIPH_EXP3_DEV_S + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h.base@1.1.4 b/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h.base@1.1.4 new file mode 100644 index 0000000..0e9746a --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/device_cfg.h.base@1.1.4 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S + +/* I2C_SBCon */ +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S + +/* I2S */ +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S + +/* ARM UART Controller PL011 */ +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S + +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S + +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S + +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S + +/** System Counter Armv8-M */ +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u + +/* System timer */ +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (25000000ul) + +/* CMSDK GPIO driver structures */ +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S + +/* System Watchdogs */ +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S + +/* ARM MPC SIE 300 driver structures */ +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S + +/* ARM PPC driver structures */ +#define PPC_SSE300_MAIN0_S +#define PPC_SSE300_MAIN0_DEV PPC_SSE300_MAIN0_DEV_S +#define PPC_SSE300_MAIN_EXP0_S +#define PPC_SSE300_MAIN_EXP0_DEV PPC_SSE300_MAIN_EXP0_DEV_S +#define PPC_SSE300_MAIN_EXP1_S +#define PPC_SSE300_MAIN_EXP1_DEV PPC_SSE300_MAIN_EXP1_DEV_S +#define PPC_SSE300_MAIN_EXP2_S +#define PPC_SSE300_MAIN_EXP2_DEV PPC_SSE300_MAIN_EXP2_DEV_S +#define PPC_SSE300_MAIN_EXP3_S +#define PPC_SSE300_MAIN_EXP3_DEV PPC_SSE300_MAIN_EXP3_DEV_S +#define PPC_SSE300_PERIPH0_S +#define PPC_SSE300_PERIPH0_DEV PPC_SSE300_PERIPH0_DEV_S +#define PPC_SSE300_PERIPH1_S +#define PPC_SSE300_PERIPH1_DEV PPC_SSE300_PERIPH1_DEV_S +#define PPC_SSE300_PERIPH_EXP0_S +#define PPC_SSE300_PERIPH_EXP0_DEV PPC_SSE300_PERIPH_EXP0_DEV_S +#define PPC_SSE300_PERIPH_EXP1_S +#define PPC_SSE300_PERIPH_EXP1_DEV PPC_SSE300_PERIPH_EXP1_DEV_S +#define PPC_SSE300_PERIPH_EXP2_S +#define PPC_SSE300_PERIPH_EXP2_DEV PPC_SSE300_PERIPH_EXP2_DEV_S +#define PPC_SSE300_PERIPH_EXP3_S +#define PPC_SSE300_PERIPH_EXP3_DEV PPC_SSE300_PERIPH_EXP3_DEV_S + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src b/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src new file mode 100644 index 0000000..2e2ef6f --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/gcc_linker_script.ld.src @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + 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) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __noinit_start + * __noinit_end + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .boot : + { + KEEP(*(.vectors)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .text : + { + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM1 + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM1 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM1 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + LONG (LOADADDR(.init_buf)) + LONG (ADDR(.init_buf)) + LONG (SIZEOF(.init_buf) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM1 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM1 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM1 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM1 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit (NOLOAD) : + { + . = ALIGN(4); + __noinit_start = .; + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + __noinit_end = .; + } > RAM0 + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + /* Non-initialized buffers in fast access RAM */ + .cache (NOLOAD): + { + . = ALIGN(32); + *(*ethos_cache_buf) /* Ethos-U Cache Area */ + *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + } > RAM1 + + /* Initialized buffers in fast access RAM */ + /* Entry must exist in .copy.table */ + .init_buf : + { + /* Add objects that go into RAM1 */ + } > RAM1 AT > ROM1 + + .rom2 : + { + *(*nn_model) /* NN Model Binary Representation */ + } > ROM2 + + .rom3 : + { + /* Add objects that go into ROM3 */ + } > ROM3 +} diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src b/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src new file mode 100644 index 0000000..ea02d53 --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/iar_linker_script.icf.src @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define memory mem with size = 4G; + +#if __ROM0_SIZE > 0 + define region ROM0_region = mem:[from __ROM0_BASE to (__ROM0_BASE+__ROM0_SIZE-1)]; +#else + define region ROM0_region = []; +#endif + +#if __ROM1_SIZE > 0 + define region ROM1_region = mem:[from __ROM1_BASE to (__ROM1_BASE+__ROM1_SIZE-1)]; +#else + define region ROM1_region = []; +#endif + +#if __ROM2_SIZE > 0 + define region ROM2_region = mem:[from __ROM2_BASE to (__ROM2_BASE+__ROM2_SIZE-1)]; +#else + define region ROM2_region = []; +#endif + +#if __ROM3_SIZE > 0 + define region ROM3_region = mem:[from __ROM3_BASE to (__ROM3_BASE+__ROM3_SIZE-1)]; +#else + 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 + define region RAM0_region = []; +#endif + +#if __RAM1_SIZE > 0 + define region RAM1_region = mem:[from __RAM1_BASE to (__RAM1_BASE+__RAM1_SIZE-1)]; +#else + define region RAM1_region = []; +#endif + +#if __RAM2_SIZE > 0 + define region RAM2_region = mem:[from __RAM2_BASE to (__RAM2_BASE+__RAM2_SIZE-1)]; +#else + define region RAM2_region = []; +#endif + +#if __RAM3_SIZE > 0 + define region RAM3_region = mem:[from __RAM3_BASE to (__RAM3_BASE+__RAM3_SIZE-1)]; +#else + 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)) +{ + // Required in a multi-threaded application + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +place at address mem:__ROM0_BASE { readonly section .intvec }; + +if (!isempty(ROM_region)) +{ + place in ROM_region { readonly }; +} + +if (!isempty(RAM_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 }; +} diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c b/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c new file mode 100644 index 0000000..b29bff1 --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2022-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM55.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE300MPS3.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(MGMT_PPU_Handler) +DEFAULT_IRQ_HANDLER(SYS_PPU_Handler) +DEFAULT_IRQ_HANDLER(CPU0_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +DEFAULT_IRQ_HANDLER(ETHOS_U55_Handler) +#ifdef CORSTONE300_AN547 +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Combined_Handler) +#endif +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Handler) +#ifdef CORSTONE300_FVP +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) +#endif +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + MGMT_PPU_Handler, /* 14: MGMT PPU Handler */ + SYS_PPU_Handler, /* 15: SYS PPU Handler */ + CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + DEBUG_PPU_Handler, /* 26: DEBUG PPU Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + ETHOS_U55_Handler, /* 56: Ethos-U55 Handler */ +#ifdef CORSTONE300_AN547 + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + DMA_Ch_1_Error_Handler, /* 60: DMA Ch1 Error Handler */ + DMA_Ch_1_Terminal_Count_Handler, /* 61: DMA Ch1 Terminal Count Handler */ + DMA_Ch_1_Combined_Handler, /* 62: DMA Ch1 Combined Handler */ + DMA_Ch_2_Error_Handler, /* 63: DMA Ch2 Error Handler */ + DMA_Ch_2_Terminal_Count_Handler, /* 64: DMA Ch2 Terminal Count Handler */ + DMA_Ch_2_Combined_Handler, /* 65: DMA Ch2 Combined Handler */ + DMA_Ch_3_Error_Handler, /* 66: DMA Ch3 Error Handler */ + DMA_Ch_3_Terminal_Count_Handler, /* 67: DMA Ch3 Terminal Count Handler */ + DMA_Ch_3_Combined_Handler, /* 68: DMA Ch3 Combined Handler */ +#else + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ +#endif + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Handler, /* 127: UART 5 combined Interrupt */ + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ +#ifdef CORSTONE300_FVP + 0, /* 131: Reserved */ + 0, /* 132: Reserved */ + 0, /* 133: Reserved */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +#endif +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c.base@1.1.1 b/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c.base@1.1.1 new file mode 100644 index 0000000..b29bff1 --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/startup_SSE300MPS3.c.base@1.1.1 @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2022-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM55.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE300MPS3.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(MGMT_PPU_Handler) +DEFAULT_IRQ_HANDLER(SYS_PPU_Handler) +DEFAULT_IRQ_HANDLER(CPU0_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +DEFAULT_IRQ_HANDLER(ETHOS_U55_Handler) +#ifdef CORSTONE300_AN547 +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Combined_Handler) +#endif +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Handler) +#ifdef CORSTONE300_FVP +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) +#endif +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + MGMT_PPU_Handler, /* 14: MGMT PPU Handler */ + SYS_PPU_Handler, /* 15: SYS PPU Handler */ + CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + DEBUG_PPU_Handler, /* 26: DEBUG PPU Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + ETHOS_U55_Handler, /* 56: Ethos-U55 Handler */ +#ifdef CORSTONE300_AN547 + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + DMA_Ch_1_Error_Handler, /* 60: DMA Ch1 Error Handler */ + DMA_Ch_1_Terminal_Count_Handler, /* 61: DMA Ch1 Terminal Count Handler */ + DMA_Ch_1_Combined_Handler, /* 62: DMA Ch1 Combined Handler */ + DMA_Ch_2_Error_Handler, /* 63: DMA Ch2 Error Handler */ + DMA_Ch_2_Terminal_Count_Handler, /* 64: DMA Ch2 Terminal Count Handler */ + DMA_Ch_2_Combined_Handler, /* 65: DMA Ch2 Combined Handler */ + DMA_Ch_3_Error_Handler, /* 66: DMA Ch3 Error Handler */ + DMA_Ch_3_Terminal_Count_Handler, /* 67: DMA Ch3 Terminal Count Handler */ + DMA_Ch_3_Combined_Handler, /* 68: DMA Ch3 Combined Handler */ +#else + 0, /* 57: Reserved */ + 0, /* 58: Reserved */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ +#endif + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Handler, /* 127: UART 5 combined Interrupt */ + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ +#ifdef CORSTONE300_FVP + 0, /* 131: Reserved */ + 0, /* 132: Reserved */ + 0, /* 133: Reserved */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +#endif +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c b/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c new file mode 100644 index 0000000..20b624e --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM55.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE300MPS3.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (32000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Set low-power state for PDEPU */ + /* 0b00 | ON, PDEPU is not in low-power state */ + /* 0b01 | ON, but the clock is off */ + /* 0b10 | RET(ention) */ + /* 0b11 | OFF */ + + /* Clear ELPSTATE, value is 0b11 on Cold reset */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk); + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c.base@1.1.1 b/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c.base@1.1.1 new file mode 100644 index 0000000..20b624e --- /dev/null +++ b/board/Corstone-300/RTE/Device/SSE-300-MPS3/system_SSE300MPS3.c.base@1.1.1 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM55.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE300MPS3.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (32000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Set low-power state for PDEPU */ + /* 0b00 | ON, PDEPU is not in low-power state */ + /* 0b01 | ON, but the clock is off */ + /* 0b10 | RET(ention) */ + /* 0b11 | OFF */ + + /* Clear ELPSTATE, value is 0b11 on Cold reset */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk); + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-300/ethos_setup.c b/board/Corstone-300/ethos_setup.c new file mode 100644 index 0000000..f154c77 --- /dev/null +++ b/board/Corstone-300/ethos_setup.c @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + + #include + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "ethosu_driver.h" +#include "main.h" + +#if defined(ETHOSU65) || defined(ETHOSU85) +/* Define Ethos-U NPU cache buffer size */ +#ifndef ETHOS_CACHE_BUF_SIZE +#define ETHOS_CACHE_BUF_SIZE 393216 +#endif + +/* Define Ethos-U cache buffer alignment */ +#ifndef ETHOS_CACHE_BUF_ALIGNMENT +#define ETHOS_CACHE_BUF_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))) +#endif +#endif + +/* Define Ethos-U NPU security mode */ +#ifndef ETHOS_SECURE_ENABLE +#define ETHOS_SECURE_ENABLE 1 +#endif + +/* Define Ethos-U NPU privilege mode */ +#ifndef ETHOS_PRIVILEGE_ENABLE +#define ETHOS_PRIVILEGE_ENABLE 1 +#endif + +/* 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; +#endif + +/* + Ethos NPU interrupt handler. +*/ +void ETHOS_U55_Handler (void) { + ethosu_irq_handler(&EthosDriver); +} + +/* + Initialize the Ethos NPU driver. +*/ +void ethos_setup (void) { + void * const ethos_base_addr = (void *)ETHOS_U55_APB_BASE_S; + struct ethosu_hw_info hw_info; + int rval; + + /* 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 */ + #else + 0, /* Cache memory pointer */ + 0, /* Cache memory size */ + #endif + ETHOS_SECURE_ENABLE, /* Secure enable */ + ETHOS_PRIVILEGE_ENABLE); /* Privileged mode */ + if (rval != 0) { + printf("Failed to initialize Arm Ethos-U driver\n"); + } + else { + NVIC_EnableIRQ(ETHOS_U55_IRQn); + + ethosu_get_hw_info(&EthosDriver, &hw_info); + + printf("Ethos-U version info:\n"); + printf("\tArch: v%u.%u.%u\n", hw_info.version.arch_major_rev, + hw_info.version.arch_minor_rev, + hw_info.version.arch_patch_rev); + printf("\tMACs/cc: %u\n", (uint32_t)(1 << hw_info.cfg.macs_per_cc)); + printf("\tCmd stream: v%u\n", hw_info.cfg.cmd_stream_version); + } +} diff --git a/board/Corstone-300/fvp_config.txt b/board/Corstone-300/fvp_config.txt new file mode 100644 index 0000000..364e9b7 --- /dev/null +++ b/board/Corstone-300/fvp_config.txt @@ -0,0 +1,7 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#------------------------------------------------------------------------------ +ethosu.num_macs=128 # (int , init-time) default = '0x80' : Number of 8x8 MACs performed per cycle (32, 64, 128, or 256). : [0x20:0x100] +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/board/Corstone-300/main.c b/board/Corstone-300/main.c new file mode 100644 index 0000000..69b3485 --- /dev/null +++ b/board/Corstone-300/main.c @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "main.h" + +int main (void) { + + /* Initialize STDIO */ + stdio_init(); + + #if defined(ETHOSU_ARCH) + /* Initialize Ethos NPU */ + ethos_setup(); + #endif + + return (app_main()); +} diff --git a/board/Corstone-300/main.h b/board/Corstone-300/main.h new file mode 100644 index 0000000..6e2048e --- /dev/null +++ b/board/Corstone-300/main.h @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2020-2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef MAIN_H__ +#define MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototypes */ +extern int app_main (void); +extern int stdio_init (void); + +#if defined(ETHOSU_ARCH) +extern void ethos_setup (void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/Corstone-300/regions_SSE-300.h b/board/Corstone-300/regions_SSE-300.h new file mode 100644 index 0000000..c55a6aa --- /dev/null +++ b/board/Corstone-300/regions_SSE-300.h @@ -0,0 +1,115 @@ +#ifndef REGIONS_SSE_300_H +#define REGIONS_SSE_300_H + +#include "sse300_memmap_s.h" +#include "sse300_memmap_ns.h" + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// ROM Configuration +// ======================= +// __ROM0 +// Base address +// Defines base address of memory region. +// Contains Startup and Vector Table +// Default: ITCM_S_BASE +#define __ROM0_BASE ITCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: ITCM_S_SIZE +#define __ROM0_SIZE ITCM_S_SIZE +// + +// __ROM1 +// Base address +// Defines base address of memory region. +// Default: FPGA_SRAM_S_BASE +#define __ROM1_BASE FPGA_SRAM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: FPGA_SRAM_S_SIZE +#define __ROM1_SIZE FPGA_SRAM_S_SIZE +// + +// __ROM2 +// Base address +// Defines base address of memory region. +// Default: DDR4_3_S_BASE +#define __ROM2_BASE DDR4_3_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_3_S_SIZE +#define __ROM2_SIZE DDR4_3_S_SIZE +// + +// __ROM3 +// Base address +// Defines base address of memory region. +// Default: QSPI_FLASH_S_BASE +#define __ROM3_BASE QSPI_FLASH_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: QSPI_FLASH_S_SIZE +#define __ROM3_SIZE QSPI_FLASH_S_SIZE +// + +// + +// RAM Configuration +// ======================= +// __RAM0 +// Base address +// Defines base address of memory region. +// Default: DDR4_1_S_BASE +#define __RAM0_BASE DDR4_1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_1_S_SIZE +#define __RAM0_SIZE DDR4_1_S_SIZE +// + +// __RAM1 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM0_S_BASE +#define __RAM1_BASE SRAM_VM0_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM0_S_SIZE +#define __RAM1_SIZE SRAM_VM0_S_SIZE +// + +// __RAM2 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM1_S_BASE +#define __RAM2_BASE SRAM_VM1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM1_S_SIZE +#define __RAM2_SIZE SRAM_VM1_S_SIZE +// + +// __RAM3 +// Base address +// Defines base address of memory region. +// Default: DTCM_S_BASE +#define __RAM3_BASE DTCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DTCM_S_SIZE +#define __RAM3_SIZE DTCM_S_SIZE +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00001000 +#define __HEAP_SIZE 0x00018000 +// + +#endif /* REGIONS_SSE_300_H */ diff --git a/board/Corstone-300/retarget_stdio.c b/board/Corstone-300/retarget_stdio.c new file mode 100644 index 0000000..f553eed --- /dev/null +++ b/board/Corstone-300/retarget_stdio.c @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Name: retarget_stdio.c + * Purpose: Retarget stdio to CMSIS UART + * + *---------------------------------------------------------------------------*/ + +#ifdef CMSIS_target_header +#include CMSIS_target_header +#else +#include "Driver_USART.h" +#endif + +#ifndef RETARGET_STDIO_UART +#error "RETARGET_STDIO_UART not defined!" +#endif + +/* Compile-time configuration */ +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif + +/* References to the external retarget functions */ +extern int stdio_init (void); +extern int stderr_putchar (int ch); +extern int stdout_putchar (int ch); +extern int stdin_getchar (void); + +/* Reference to the underlying USART driver */ +#ifndef CMSIS_target_header +extern ARM_DRIVER_USART ARM_Driver_USART_(RETARGET_STDIO_UART); +#endif +#define ptrUSART (&ARM_Driver_USART_(RETARGET_STDIO_UART)) + +/** + Initialize stdio + + \return 0 on success, or -1 on error. +*/ +int stdio_init (void) { + + if (ptrUSART->Initialize(NULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | + ARM_USART_DATA_BITS_8 | + ARM_USART_PARITY_NONE | + ARM_USART_STOP_BITS_1 | + ARM_USART_FLOW_CONTROL_NONE, + UART_BAUDRATE) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_RX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_TX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + return 0; +} + +/** + Put a character to the stderr + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stderr_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Put a character to the stdout + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stdout_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Get a character from the stdio + + \return The next character from the input, or -1 on read error. +*/ +int stdin_getchar (void) { + uint8_t buf[1]; + + if (ptrUSART->Receive(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().rx_busy != 0U); + + return (int)buf[0]; +} \ No newline at end of file diff --git a/board/Corstone-300/sse300_memmap_ns.h b/board/Corstone-300/sse300_memmap_ns.h new file mode 100644 index 0000000..d15a465 --- /dev/null +++ b/board/Corstone-300/sse300_memmap_ns.h @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE300_MEMMAP_NS_H +#define SSE300_MEMMAP_NS_H + +/*============================================================================*/ +/* NON-SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Non-Secure */ +#define ITCM_NS_BASE 0x00000000 +#define ITCM_NS_SIZE 0x00080000 /* 512KB */ +#define ITCM_NS_LIMIT (ITCM_NS_BASE + ITCM_NS_SIZE - 1) + +/* FPGA SRAM - Non-Secure */ +#define FPGA_SRAM_NS_BASE 0x01000000 +#define FPGA_SRAM_NS_SIZE 0x00100000 /* 1MB */ +#define FPGA_SRAM_NS_LIMIT (FPGA_SRAM_NS_BASE + FPGA_SRAM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Non-Secure */ +#define DTCM_NS_BASE 0x20000000 +#define DTCM_NS_SIZE 0x00080000 /* 512KB */ +#define DTCM_NS_LIMIT (DTCM_NS_BASE + DTCM_NS_SIZE - 1) + +/* SRAM VM0 - Non-Secure */ +#define SRAM_VM0_NS_BASE 0x21000000 +#define SRAM_VM0_NS_SIZE 0x00100000 /* 1MB */ +#define SRAM_VM0_NS_LIMIT (SRAM_VM0_NS_BASE + SRAM_VM0_NS_SIZE - 1) + +/* SRAM VM1 - Non-Secure */ +#define SRAM_VM1_NS_BASE 0x21100000 +#define SRAM_VM1_NS_SIZE 0x00100000 /* 1MB */ +#define SRAM_VM1_NS_LIMIT (SRAM_VM1_NS_BASE + SRAM_VM1_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_NS_BASE 0x28000000 +#define QSPI_FLASH_NS_SIZE 0x00800000 /* 8MB */ +#define QSPI_FLASH_NS_LIMIT (QSPI_FLASH_NS_BASE + QSPI_FLASH_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 0 - Non-Secure */ +#define DDR4_0_NS_BASE 0x60000000 +#define DDR4_0_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_0_NS_LIMIT (DDR4_0_NS_BASE + DDR4_0_NS_SIZE - 1) + +/* DDR4 Region 2 - Non-Secure */ +#define DDR4_2_NS_BASE 0x80000000 +#define DDR4_2_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_2_NS_LIMIT (DDR4_2_NS_BASE + DDR4_2_NS_SIZE - 1) + +/* DDR4 Region 4 - Non-Secure */ +#define DDR4_4_NS_BASE 0xA0000000 +#define DDR4_4_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_4_NS_LIMIT (DDR4_4_NS_BASE + DDR4_4_NS_SIZE - 1) + +/* DDR4 Region 6 - Non-Secure */ +#define DDR4_6_NS_BASE 0xC0000000 +#define DDR4_6_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_6_NS_LIMIT (DDR4_6_NS_BASE + DDR4_6_NS_SIZE - 1) + +#endif /* SSE300_MEMMAP_NS_H */ diff --git a/board/Corstone-300/sse300_memmap_s.h b/board/Corstone-300/sse300_memmap_s.h new file mode 100644 index 0000000..3746461 --- /dev/null +++ b/board/Corstone-300/sse300_memmap_s.h @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE300_MEMMAP_S_H +#define SSE300_MEMMAP_S_H + +/*============================================================================*/ +/* SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Secure (Startup) */ +#define ITCM_S_BASE 0x10000000 +#define ITCM_S_SIZE 0x00080000 /* 512KB */ +#define ITCM_S_LIMIT (ITCM_S_BASE + ITCM_S_SIZE - 1) + +/* FPGA SRAM - Secure */ +#define FPGA_SRAM_S_BASE 0x11000000 +#define FPGA_SRAM_S_SIZE 0x00100000 /* 1MB */ +#define FPGA_SRAM_S_LIMIT (FPGA_SRAM_S_BASE + FPGA_SRAM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Secure */ +#define DTCM_S_BASE 0x30000000 +#define DTCM_S_SIZE 0x00080000 /* 512KB */ +#define DTCM_S_LIMIT (DTCM_S_BASE + DTCM_S_SIZE - 1) + +/* SRAM VM0 - Secure */ +#define SRAM_VM0_S_BASE 0x31000000 +#define SRAM_VM0_S_SIZE 0x00100000 /* 1MB */ +#define SRAM_VM0_S_LIMIT (SRAM_VM0_S_BASE + SRAM_VM0_S_SIZE - 1) + +/* SRAM VM1 - Secure */ +#define SRAM_VM1_S_BASE 0x31100000 +#define SRAM_VM1_S_SIZE 0x00100000 /* 1MB */ +#define SRAM_VM1_S_LIMIT (SRAM_VM1_S_BASE + SRAM_VM1_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_S_BASE 0x38000000 +#define QSPI_FLASH_S_SIZE 0x00800000 /* 8MB */ +#define QSPI_FLASH_S_LIMIT (QSPI_FLASH_S_BASE + QSPI_FLASH_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 1 - Secure */ +#define DDR4_1_S_BASE 0x70000000 +#define DDR4_1_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_1_S_LIMIT (DDR4_1_S_BASE + DDR4_1_S_SIZE - 1) + +/* DDR4 Region 3 - Secure */ +#define DDR4_3_S_BASE 0x90000000 +#define DDR4_3_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_3_S_LIMIT (DDR4_3_S_BASE + DDR4_3_S_SIZE - 1) + +/* DDR4 Region 5 - Secure */ +#define DDR4_5_S_BASE 0xB0000000 +#define DDR4_5_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_5_S_LIMIT (DDR4_5_S_BASE + DDR4_5_S_SIZE - 1) + +/* DDR4 Region 7 - Secure */ +#define DDR4_7_S_BASE 0xD0000000 +#define DDR4_7_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_7_S_LIMIT (DDR4_7_S_BASE + DDR4_7_S_SIZE - 1) + +#endif /* SSE300_MEMMAP_S_H */ diff --git a/board/Corstone-300/vsi/python/arm_vsi0.py b/board/Corstone-300/vsi/python/arm_vsi0.py new file mode 100644 index 0000000..e1a7bfc --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi0.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 0 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi0_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6000) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/arm_vsi1.py b/board/Corstone-300/vsi/python/arm_vsi1.py new file mode 100644 index 0000000..f1271b5 --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi1.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 1 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi1_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6001) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/arm_vsi4.py b/board/Corstone-300/vsi/python/arm_vsi4.py new file mode 100644 index 0000000..e15edf8 --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi4.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 4 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi4_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6004) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/arm_vsi5.py b/board/Corstone-300/vsi/python/arm_vsi5.py new file mode 100644 index 0000000..631f74d --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi5.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 5 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi5_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6005) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/arm_vsi6.py b/board/Corstone-300/vsi/python/arm_vsi6.py new file mode 100644 index 0000000..58b1184 --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi6.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 6 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi6_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6006) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/arm_vsi7.py b/board/Corstone-300/vsi/python/arm_vsi7.py new file mode 100644 index 0000000..cd32ab8 --- /dev/null +++ b/board/Corstone-300/vsi/python/arm_vsi7.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 7 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi7_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6007) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-300/vsi/python/vsi_audio.py b/board/Corstone-300/vsi/python/vsi_audio.py new file mode 100644 index 0000000..a71574a --- /dev/null +++ b/board/Corstone-300/vsi/python/vsi_audio.py @@ -0,0 +1,543 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) audio server. +# It allows configuration, streaming, and audio data transfer operations, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Audio:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Audio:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class AudioClient: + """ + Client for communicating with the VSI audio server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive audio data, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Audio format codes + self.PCM_S8 = 0 + self.PCM_S16LE = 1 + self.PCM_S24LE = 2 + self.PCM_S32LE = 3 + self.PCM_F32LE = 4 + + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI audio server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the audio stream (input/output). + Args: + mode: 1 for input, 2 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the audio streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the audio stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters on the server. + Args: + channels: Number of audio channels (1=mono, 2=stereo). + sample_rate: Sample rate in Hz (e.g., 44100, 48000). + sample_bits: Bit depth (8, 16, 24, 32). + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, channels, sample_rate, sample_bits]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the audio stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the audio stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readAudio(self, size): + """ + Request audio data from the server. + Args: + size: Number of bytes to read. + Returns: + tuple: (data, eos) where data is a Bytearray of audio data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.AUDIO_READ, size]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeAudio(self, data): + """ + Send audio data to the server. + Args: + data: Bytearray of audio data to write. + Returns: + None + """ + self.conn.send([self.AUDIO_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +CHANNELS = 1 # Regs[4] // Number of audio channels +SAMPLE_RATE = 16000 # Regs[5] // Sample rate +SAMPLE_BITS = 16 # Regs[6] // Bits per sample + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Audio.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Audio.configureStream(CHANNELS, SAMPLE_RATE, SAMPLE_BITS) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Audio.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Audio.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Audio.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Audio.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = CHANNELS + elif index == 5: + value = SAMPLE_RATE + elif index == 6: + value = SAMPLE_BITS + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + CHANNELS = value + elif index == 5: + SAMPLE_RATE = value + elif index == 6: + SAMPLE_BITS = value + + return value diff --git a/board/Corstone-300/vsi/python/vsi_audio_server.py b/board/Corstone-300/vsi/python/vsi_audio_server.py new file mode 100644 index 0000000..dafa594 --- /dev/null +++ b/board/Corstone-300/vsi/python/vsi_audio_server.py @@ -0,0 +1,691 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Server module + +try: + import argparse + import ipaddress + import logging + import time + import wave + from multiprocessing.connection import Listener + from pathlib import Path + + import pyaudio + import numpy as np +except ImportError as err: + print(f"VSI:Audio:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Audio:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Audio Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6001) +default_authkey = 'vsi_audio' + +# Supported file extensions +supported_files = ['wav'] + +# Mode Input/Output +MODE_AUDIO_NONE = 0 +MODE_AUDIO_INPUT = 1 +MODE_AUDIO_OUTPUT = 2 + +class AudioServer: + """Implements a TCP server for audio streaming and sample I/O. + + Supports both audio files and microphone/speaker devices as input/output. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing audio data), and performs the requested audio + operations using PyAudio and wave modules. + """ + def __init__(self, address, authkey): + """ + Initialize the AudioServer. + + Sets up command codes, audio format constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.eos = False + self.stream = None + self.wave_file = None + self.pyaudio_obj = pyaudio.PyAudio() + self.audio_buffer = bytearray() + self.chunk_size = 1024 + + # Stream configuration + self.channels = None + self.sample_rate = None + self.sample_bits = None + + def _setMode(self, mode): + """ + Set the stream mode to input (microphone/file) or output (speakers/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_AUDIO_INPUT: + self.mode = MODE_AUDIO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_AUDIO_OUTPUT: + self.mode = MODE_AUDIO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_AUDIO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_audio_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in supported_files: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_AUDIO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_AUDIO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters. + + Args: + channels: The number of audio channels (1=mono, 2=stereo). + sample_rate: The sample rate in Hz (8000, 16000, 44100, 48000). + sample_bits: The bit depth (8, 16, 24, 32). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits}") + + if channels <= 0 or sample_rate <= 0 or sample_bits <= 0: + logger.error(f"_configureStream: invalid argument (channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits})") + return False + + if sample_bits not in [8, 16, 24, 32]: + logger.error(f"_configureStream: unsupported sample_bits={sample_bits}") + return False + + self.channels = channels + self.sample_rate = sample_rate + self.sample_bits = sample_bits + + logger.info(f"_configureStream: stream configured to {self.channels} channels, {self.sample_rate}Hz, {self.sample_bits} bits") + + return True + + def _get_pyaudio_format(self): + """Get PyAudio format based on sample bits.""" + if self.sample_bits == 8: + return pyaudio.paUInt8 + elif self.sample_bits == 16: + return pyaudio.paInt16 + elif self.sample_bits == 24: + return pyaudio.paInt24 + elif self.sample_bits == 32: + return pyaudio.paInt32 + else: + return pyaudio.paInt16 # default + + def _scan_audio_devices(self): + """ + Scan and log available audio devices, separating input and output devices. + Returns: + Default device index for the current mode. + """ + if self.pyaudio_obj is None: + logger.error(" _scan_audio_devices: PyAudio object is not initialized") + return 0 + + logger.info("=== Available Audio Devices ===") + device_count = self.pyaudio_obj.get_device_count() + + input_devices = [] + output_devices = [] + + # Scan all devices + for i in range(device_count): + try: + info = self.pyaudio_obj.get_device_info_by_index(i) + host_api_info = self.pyaudio_obj.get_host_api_info_by_index(info['hostApi']) + + device_info = { + 'index': i, + 'name': info['name'], + 'max_input_channels': info['maxInputChannels'], + 'max_output_channels': info['maxOutputChannels'], + 'default_sample_rate': info['defaultSampleRate'], + 'host_api': host_api_info['name'] + } + + # Categorize devices + if info['maxInputChannels'] > 0: + input_devices.append(device_info) + if info['maxOutputChannels'] > 0: + output_devices.append(device_info) + + except Exception as e: + logger.warning(f"Device {i}: Error reading device info - {e}") + + # Retrieve default devices + try: + default_input = self.pyaudio_obj.get_default_input_device_info() + default_output = self.pyaudio_obj.get_default_output_device_info() + except Exception as e: + logger.warning(f"Error getting default devices: {e}") + + if (self.mode == MODE_AUDIO_INPUT): + # Log input devices + logger.info("--- INPUT DEVICES ---") + if input_devices: + for device in input_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Input Channels: {device['max_input_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No input devices found") + + logger.info(f"Default Input Device: {default_input['index']} - {default_input['name']}") + + rval = default_input['index'] + + if (self.mode == MODE_AUDIO_OUTPUT): + # Log output devices + logger.debug("--- OUTPUT DEVICES ---") + if output_devices: + for device in output_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Output Channels: {device['max_output_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No output devices found") + + logger.info(f"Default Output Device: {default_output['index']} - {default_output['name']}") + + rval = default_output['index'] + + return rval + + def _audio_callback_input(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio input stream. + """ + logger.debug(f"_audio_callback_input: received {len(in_data)} bytes") + + self.audio_buffer.extend(in_data) + return (None, pyaudio.paContinue) + + def _audio_callback_output(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio output stream. + """ + logger.debug(f"_audio_callback_output: requested {frame_count} frames") + + bytes_needed = frame_count * self.channels * (self.sample_bits // 8) + if len(self.audio_buffer) >= bytes_needed: + data = bytes(self.audio_buffer[:bytes_needed]) + del self.audio_buffer[:bytes_needed] + else: + # Not enough data, return silence + data = b'\x00' * bytes_needed + return (data, pyaudio.paContinue) + + def _enableStream(self): + """ + Enable the audio stream for input (microphone/file) or output (file/speakers). + + Initializes the PyAudio stream or wave file as needed. + Returns: + None + """ + if self.mode != MODE_AUDIO_INPUT and self.mode != MODE_AUDIO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.audio_buffer.clear() + + try: + if self.filename == None: + # Use microphone/speakers + if self.pyaudio_obj is None: + logger.error("_enableStream: PyAudio object is not initialized") + return + + audio_format = self._get_pyaudio_format() + + if self.mode == MODE_AUDIO_INPUT: + logger.debug("_enableStream: use microphone for input streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + input=True, + input_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_input + ) + self.stream.start_stream() + + elif self.mode == MODE_AUDIO_OUTPUT: + logger.debug("_enableStream: use speakers for output streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + output=True, + output_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_output + ) + self.stream.start_stream() + + logger.info(f"_enableStream: audio device stream properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + else: + # Set file name string for audio file + file = str(self.filename.absolute()) + + logger.debug(f"_enableStream: use audio file: {file}") + + if self.mode == MODE_AUDIO_INPUT: + self.wave_file = wave.open(file, 'rb') + + # Verify file properties match configuration + file_channels = self.wave_file.getnchannels() + file_rate = self.wave_file.getframerate() + file_bits = self.wave_file.getsampwidth() * 8 + + if (file_channels != self.channels or file_rate != self.sample_rate or file_bits != self.sample_bits): + logger.warning(f"_enableStream: file properties ({file_channels}ch, {file_rate}Hz, {file_bits}bit) " + f"don't match configured ({self.channels}ch, {self.sample_rate}Hz, {self.sample_bits}bit)") + + logger.info(f"_enableStream: input file properties: channels={file_channels}, rate={file_rate}, bits={file_bits}") + + elif self.mode == MODE_AUDIO_OUTPUT: + self.wave_file = wave.open(file, 'wb') + self.wave_file.setnchannels(self.channels) + self.wave_file.setsampwidth(self.sample_bits // 8) + self.wave_file.setframerate(self.sample_rate) + + logger.info(f"_enableStream: output file properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + self.active = True + logger.info("_enableStream: stream enabled") + + except Exception as e: + logger.error(f"_enableStream: failed to enable stream: {e}") + self._disableStream() + + def _disableStream(self): + """ + Disable the audio stream and release resources. + + Returns: + None + """ + self.active = False + + try: + if self.stream is not None: + if self.stream.is_active(): + self.stream.stop_stream() + self.stream.close() + self.stream = None + + if self.pyaudio_obj is not None: + self.pyaudio_obj.terminate() + self.pyaudio_obj = None + + if self.wave_file is not None: + self.wave_file.close() + self.wave_file = None + + except Exception as e: + logger.error(f"_disableStream: error during cleanup: {e}") + + logger.info("_disableStream: stream disabled") + + def _readAudio(self, size): + """ + Read audio data from the current source. + + Args: + size: Number of bytes to read. + Returns: + audio_data: The read audio data as a bytearray, or empty if no data is available. + """ + logger.debug(f"_readAudio: size={size} bytes") + + audio_data = bytearray() + + if not self.active: + logger.error("_readAudio: stream not active") + return audio_data + + if self.eos: + logger.debug("_readAudio: end of stream") + return audio_data + + try: + if self.filename == None: + # Read from microphone buffer + while len(self.audio_buffer) < size: + # Wait for enough data + time.sleep(0.01) # Wait 10ms + + # Now we have enough data + audio_data = bytearray(self.audio_buffer[:size]) + del self.audio_buffer[:size] + + logger.debug(f"_readAudio: read {len(audio_data)} bytes from microphone buffer") + + else: + # Read from wave file + frames_to_read = size // (self.channels * (self.sample_bits // 8)) + frames_data = self.wave_file.readframes(frames_to_read) + + if len(frames_data) > 0: + audio_data = bytearray(frames_data) + logger.debug(f"_readAudio: read {len(audio_data)} bytes from file") + else: + self.eos = True + logger.debug("_readAudio: end of file reached") + + except Exception as e: + logger.error(f"_readAudio: error reading audio data: {e}") + + return audio_data + + def _writeAudio(self, data): + """ + Write audio data to the output destination (file or speakers). + + Args: + data: The input audio data as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeAudio: audio data size={len(data)} bytes") + + if not self.active: + logger.error("_writeAudio: stream not active") + return + + try: + if self.filename == None: + # Write to speakers buffer + self.audio_buffer.extend(data) + logger.debug("_writeAudio: added data to speaker buffer") + + else: + # Write to wave file + self.wave_file.writeframes(data) + logger.debug("_writeAudio: wrote data to file") + + except Exception as e: + logger.error(f"_writeAudio: error writing audio data: {e}") + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write audio, close server. + Sends responses or audio data as appropriate. + """ + logger.info("Audio server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.AUDIO_READ: + size = payload[0] + audio_data = self._readAudio(size) + conn.send_bytes(audio_data) + conn.send(self.eos) + + elif cmd == self.AUDIO_WRITE: + audio_data = conn.recv_bytes() + self._writeAudio(audio_data) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + def stop(self): + """ + Stop the audio server. + + Releases all resources. + Returns: + None + """ + self._disableStream() + self.listener.close() + logger.info("Audio server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the audio server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Audio Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = AudioServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-300/vsi/python/vsi_video.py b/board/Corstone-300/vsi/python/vsi_video.py new file mode 100644 index 0000000..47a2af2 --- /dev/null +++ b/board/Corstone-300/vsi/python/vsi_video.py @@ -0,0 +1,547 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) video server. +# It allows configuration, streaming, and frame transfer operations for video data, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Video:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Video:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class VideoClient: + """ + Client for communicating with the VSI video server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive frames, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space codes + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI video server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the video stream (input/output). + Args: + mode: 0 for input, 1 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the video streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the video stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, frame_width, frame_height, frame_rate, color_format): + """ + Configure the video stream parameters on the server. + Args: + frame_width: Width of the video frame. + frame_height: Height of the video frame. + frame_rate: Frame rate in frames per second. + color_format: Color format code. + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, frame_width, frame_height, frame_rate, color_format]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the video stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the video stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readFrame(self): + """ + Request a video frame from the server. + Returns: + tuple: (data, eos) where data is a Bytearray of frame data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.FRAME_READ]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeFrame(self, data): + """ + Send a video frame to the server. + Args: + data: Bytearray of frame data to write. + Returns: + None + """ + self.conn.send([self.FRAME_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +FRAME_WIDTH = 300 # Regs[4] // Requested frame width +FRAME_HEIGHT = 300 # Regs[5] // Requested frame height +FRAME_RATE = 0 # Regs[6] // Frame rate +FRAME_COLOR = 0 # Regs[7] // Frame color space + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Video.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Video.configureStream(FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Video.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Video.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Video.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Video.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = FRAME_WIDTH + elif index == 5: + value = FRAME_HEIGHT + elif index == 6: + value = FRAME_RATE + elif index == 7: + value = FRAME_COLOR + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + FRAME_WIDTH = value + elif index == 5: + FRAME_HEIGHT = value + elif index == 6: + FRAME_RATE = value + elif index == 7: + FRAME_COLOR = value + + return value diff --git a/board/Corstone-300/vsi/python/vsi_video_server.py b/board/Corstone-300/vsi/python/vsi_video_server.py new file mode 100644 index 0000000..3699eb3 --- /dev/null +++ b/board/Corstone-300/vsi/python/vsi_video_server.py @@ -0,0 +1,785 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Server module + +try: + import argparse + import ipaddress + import logging + from multiprocessing.connection import Listener + from pathlib import Path + + import cv2 + import numpy as np +except ImportError as err: + print(f"VSI:Video:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Video:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Video Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6000) +default_authkey = 'vsi_video' + +# Supported file extensions +video_file_extensions = ('wmv', 'avi', 'mp4') +image_file_extensions = ('bmp', 'png', 'jpg') +video_fourcc = {'wmv' : 'WMV1', 'avi' : 'MJPG', 'mp4' : 'mp4v'} + +# Mode Input/Output +MODE_VIDEO_NONE = 0 +MODE_VIDEO_INPUT = 1 +MODE_VIDEO_OUTPUT = 2 + +class VideoServer: + """Implements a TCP server for video streaming and frame I/O. + + Supports both video and image files as input/output, and can interface with a camera device. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing frames), and performs the requested video + operations using OpenCV. + """ + def __init__(self, address, authkey): + """ + Initialize the VideoServer. + + Sets up command codes, color space constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.video = True + self.stream = None + self.frame_ratio = 0 + self.frame_drop = 0 + self.eos = False + # Stream configuration + self.frame_width = None + self.frame_height = None + self.frame_color = None + self.frame_rate = None + + + def _setMode(self, mode): + """ + Set the stream mode to input (camera/file) or output (display/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_VIDEO_INPUT: + self.mode = MODE_VIDEO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_VIDEO_OUTPUT: + self.mode = MODE_VIDEO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_VIDEO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_video_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in video_file_extensions + image_file_extensions: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_VIDEO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_VIDEO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, frame_width, frame_height, frame_rate, frame_color): + """ + Configure the video stream parameters. + + Args: + frame_width: The desired frame width in pixels. + frame_height: The desired frame height in pixels. + frame_rate: The desired frame rate in frames per second. + frame_color: The desired frame color space (one of the defined constants). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: frame_width={frame_width}, frame_height={frame_height}, frame_rate={frame_rate}, frame_color={frame_color}") + + if (frame_width == 0 or frame_height == 0 or frame_rate == 0): + logger.error(f"_configureStream: invalid argument (width={frame_width}, height={frame_height}, rate={frame_rate})") + return False + if frame_color not in (self.GRAYSCALE8, self.RGB888, self.BGR565, self.YUV420, self.NV12, self.NV21): + logger.error(f"_configureStream: invalid argument (color={frame_color})") + return False + + self.frame_width = frame_width + self.frame_height = frame_height + self.frame_rate = frame_rate + self.frame_color = frame_color + + logger.info(f"_configureStream: stream configured to {self.frame_width}x{self.frame_height}, fps={self.frame_rate}, color={self.frame_color}") + + return True + + def _scan_video_devices(self): + """ + Scan and log available video input devices. + Returns: + Default device index for the current mode. + """ + logger.info("=== Available Video Devices ===") + + available_devices = [] + + # Test device indices 0-1 (covers built-in webcam + external camera) + for device_index in range(2): + try: + cap = cv2.VideoCapture(device_index) + if cap.isOpened(): + + # Get device properties + width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + + device_info = { + 'index': device_index, + 'width': width, + 'height': height, + 'fps': fps, + } + available_devices.append(device_info) + + logger.info(f"Device {device_index}: {width}x{height} @ {fps:.1f}fps") + + cap.release() + except Exception as e: + logger.error(f"Error accessing device {device_index}: {e}") + + if not available_devices: + logger.warning("No video devices found") + return -1 + else: + logger.info(f"Found {len(available_devices)} input device(s)") + logger.info(f"Default Input Device: 0") + + return 0 + + def _enableStream(self): + """ + Enable the video stream for input (camera/file) or output (file/display). + + Initializes the OpenCV VideoCapture or VideoWriter as needed. + Handles both new and existing files, and sets up frame dropping if input FPS > requested FPS. + Returns: + None + """ + + if self.mode != MODE_VIDEO_INPUT and self.mode != MODE_VIDEO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.frame_ratio = 0 + self.frame_drop = 0 + + if self.stream is not None: + self.stream.release() + self.stream = None + + if self.filename == None: + self.video = True + + if self.video: + if self.mode == MODE_VIDEO_INPUT: + # Input mode: read from camera or video file + if self.filename == None: + # No filename specified: use camera interface + logger.debug("_enableStream: use camera interface for input streaming") + self.stream = cv2.VideoCapture(self.device) + + if not self.stream.isOpened(): + logger.error("_enableStream: failed to open Camera interface") + return + else: + # Filename specified: use video file + logger.debug("_enableStream: use file interface for input streaming") + self.stream = cv2.VideoCapture(self.filename) + + # Display stream properties + logger.info(f"_enableStream: source stream properties: width={self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)}, height={self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)}, fps={self.stream.get(cv2.CAP_PROP_FPS)}") + + # Get the video stream FPS + video_fps = self.stream.get(cv2.CAP_PROP_FPS) + + if video_fps > self.frame_rate: + self.frame_ratio = video_fps / self.frame_rate + logger.debug(f"_enableStream: source/target frame ratio={self.frame_ratio}") + + elif self.mode == MODE_VIDEO_OUTPUT: + # Output mode: write to video file or display window + if self.filename != None: + # Filename specified: output to file + logger.debug("_enableStream: output stream to a file") + + extension = self.filename.suffix.lstrip('.').lower() + fourcc = cv2.VideoWriter_fourcc(*f'{video_fourcc[extension]}') + + self.stream = cv2.VideoWriter(self.filename, fourcc, self.frame_rate, (self.frame_width, self.frame_height)) + else: + logger.debug("_enableStream: output stream to display window") + + self.active = True + logger.info("_enableStream: stream enabled") + + def _disableStream(self): + """ + Disable the video stream and release OpenCV resources. + + For input streams, saves the current frame index for resuming later. + Returns: + None + """ + self.active = False + if self.stream is not None: + # Clean-up stream resources and invalidate object + self.stream.release() + self.stream = None + + logger.info("_disableStream: stream disabled") + + def __cropFrame(self, frame, target_aspect_ratio): + """ + Crop the input frame to match the specified aspect ratio. + + Args: + frame: The input frame (as NumPy array) to be cropped. + aspect_ratio: The target aspect ratio (width/height). + Returns: + frame: The cropped frame. + """ + logger.debug(f"__cropFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_aspect_ratio={target_aspect_ratio}") + + # NumPY array shape is (height, width, channels) + frame_h = frame.shape[0] + frame_w = frame.shape[1] + + frame_aspect_ratio = frame_w / frame_h + + if frame_aspect_ratio > target_aspect_ratio: + # Frame is wider than target -> crop left and right + new_w = int(frame_h * target_aspect_ratio) + left = (frame_w - new_w) // 2 + right = left + new_w + cropped = frame[:, left:right] + else: + # Frame is taller than target -> crop top and bottom + new_h = int(frame_w / target_aspect_ratio) + top = (frame_h - new_h) // 2 + bottom = top + new_h + cropped = frame[top:bottom, :] + + logger.debug(f"__cropFrame: cropped_size=({cropped.shape[1]}, {cropped.shape[0]})") + + return cropped + + def __resizeFrame(self, frame, target_width, target_height): + """ + Resize the input frame to the target width and height. + + Args: + frame: The input frame (as NumPy array) to be resized. + target_width: The target width in pixels. + target_height: The target height in pixels. + Returns: + frame: The resized frame. + """ + logger.debug(f"__resizeFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_size=({target_width}, {target_height})") + + try: + frame = cv2.resize(frame, (target_width, target_height)) + except Exception as e: + logger.error(f"Error in resizeFrame(): {e}") + + logger.debug(f"__resizeFrame: resized_size=({frame.shape[1]}, {frame.shape[0]})") + + return frame + + def __convertToBGR(self, frame): + """ + Convert the input frame to BGR color space if needed. + + Args: + frame: The input frame (as NumPy array) to be converted. + Returns: + frame: The converted frame in BGR color space. + """ + if self.frame_color == self.RGB888: + # Convert RGB to BGR + logger.debug(f"__convertToBGR: converting frame from RGB to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) + elif self.frame_color == self.GRAYSCALE8: + # Convert Grayscale to BGR + logger.debug(f"__convertToBGR: converting frame from Grayscale to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) + elif self.frame_color == self.BGR565: + # Convert BGR565 to BGR + logger.debug(f"__convertToBGR: converting frame from BGR565 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR5652BGR) + elif self.frame_color == self.YUV420: + # Convert YUV420 to BGR + logger.debug(f"__convertToBGR: converting frame from YUV420 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_I420) + elif self.frame_color == self.NV12: + # Convert NV12 to BGR + logger.debug(f"__convertToBGR: converting frame from NV12 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV12) + elif self.frame_color == self.NV21: + # Convert NV21 to BGR + logger.debug(f"__convertToBGR: converting frame from NV21 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV21) + + return frame + + def __convertFromBGR(self, frame): + """ + Convert the input BGR frame to the specified color space if needed. + + Args: + frame: The input frame (as NumPy array in BGR color space) to be converted. + Returns: + frame: The converted frame in the specified color space. + """ + if self.frame_color == self.RGB888: + # Convert BGR to RGB + logger.debug(f"__convertFromBGR: converting frame from BGR to RGB") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + elif self.frame_color == self.GRAYSCALE8: + # Convert BGR to Grayscale + logger.debug(f"__convertFromBGR: converting frame from BGR to Grayscale") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + elif self.frame_color == self.BGR565: + # Convert BGR to BGR565 + logger.debug(f"__convertFromBGR: converting frame from BGR to BGR565") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGR565) + elif self.frame_color == self.YUV420: + # Convert BGR to YUV420 + logger.debug(f"__convertFromBGR: converting frame from BGR to YUV420") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420) + elif self.frame_color == self.NV12: + # Convert BGR to NV12 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV12") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV12) + elif self.frame_color == self.NV21: + # Convert BGR to NV21 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV21") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV21) + + return frame + + # Read frame from source + def _readFrame(self): + """Read a single frame from the current video or image source. + + If the stream is not active or end-of-stream is reached, returns an empty bytearray. + For video sources, handles frame dropping to match requested frame rate. + For image sources, reads the image once and sets end-of-stream. + Resizes and converts color space as needed. + Returns: + frame: The read frame as a bytearray, or empty if no frame is available. + """ + frame = bytearray() + + # If the stream is not active, return empty frame + if not self.active: + logger.error("_readFrame: stream not active") + return frame + + # If end-of-stream has been reached, return empty frame + if self.eos: + logger.debug("_readFrame: end of stream reached") + return frame + + if self.video: + # Video source, read frame from the video stream + _, frame_in = self.stream.read() # Frame is numpy.ndarray, (height, width, channels), dtype=uint8 + + if frame_in is not None: + logger.debug(f"_readFrame: frame captured, size=({frame_in.shape[1]}, {frame_in.shape[0]})") + + # Handle frame dropping if input FPS > requested FPS + if self.frame_ratio > 1: + # Accumulate fractional frames to drop + self.frame_drop += (self.frame_ratio - 1) + + if self.frame_drop > 1: + logger.debug(f"_readFrame: frames to drop={self.frame_drop}") + drop = int(self.frame_drop // 1) + + # Drop the required number of frames to match requested FPS + for i in range(drop): + _, _ = self.stream.read() + logger.debug(f"_readFrame: frames dropped={drop}") + self.frame_drop -= drop + logger.debug(f"_readFrame: frames left to drop={self.frame_drop}") + else: + # Frame not read, mark end-of-stream + self.eos = True + logger.debug("_readFrame: end of stream.") + else: + # For image sources, read the image once and set end-of-stream + frame_in = cv2.imread(self.filename) + self.eos = True + logger.debug("_readFrame: end of stream.") + + if frame_in is not None: + target_width = self.frame_width + target_height = self.frame_height + + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size aspect ratio + target_aspect_ratio = target_width / target_height + frame_aspect_ratio = frame_in_width / frame_in_height + + if not np.isclose(frame_aspect_ratio, target_aspect_ratio, rtol=1e-3): + logger.debug(f"_readFrame: frame aspect ratio {frame_aspect_ratio:.2f} does not match target {target_aspect_ratio:.2f}, cropping frame") + frame_in = self.__cropFrame(frame_in, target_aspect_ratio) + + # Update frame size after cropping + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size + if (frame_in_width != target_width) or (frame_in_height != target_height): + logger.debug(f"_readFrame: frame size ({frame_in_width}, {frame_in_height}) does not match target ({target_width}, {target_height}), resizing frame") + frame_in = self.__resizeFrame(frame_in, target_width, target_height) + + # Convert frame color space to target color space + frame_in = self.__convertFromBGR(frame_in) + + # Convert the frame to a bytearray for transmission + frame = bytearray(frame_in.tobytes()) + + return frame + + def _writeFrame(self, frame): + """ + Write a frame to the output destination (file or display window). + + If filename is empty, displays the frame in a window. + If filename is set and video mode, writes frame to video file. + If filename is set and image mode, saves frame as image file. + Args: + frame: The input frame as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeFrame: frame size={len(frame)} bytes") + + # If the stream is not active, do nothing + if not self.active: + logger.error("_writeFrame: stream not active") + return + + try: + # Decode the frame from bytearray to a NumPy array + decoded_frame = np.frombuffer(frame, dtype=np.uint8) + + # Reshape the decoded frame to match the target resolution + decoded_frame = decoded_frame.reshape((self.frame_height, self.frame_width, 3)) + logger.debug(f"_writeFrame: decoded frame size=({decoded_frame.shape[1]}, {decoded_frame.shape[0]})") + + # Convert color space to BGR + frame_out = self.__convertToBGR(decoded_frame) + + if self.filename == None: + logger.debug("_writeFrame: display frame in window") + # If no filename, display the frame in a window + cv2.imshow(self.filename, frame_out) + cv2.waitKey(10) + else: + if self.video: + logger.debug("_writeFrame: write frame to video file") + # Write frame to video file + self.stream.write(np.uint8(frame_out)) + else: + logger.debug("_writeFrame: write frame as image file") + # Write frame as image file + cv2.imwrite(self.filename, frame_out) + + except Exception as e: + # Output exception debug information but continue + logger.error(f"Exception in _writeFrame: {type(e).__name__}: {e}", exc_info=True) + pass + + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write frames, close server. + Sends responses or frame data as appropriate. + """ + logger.info("Video server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2], payload[3]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.FRAME_READ: + frame = self._readFrame() + conn.send_bytes(frame) + conn.send(self.eos) + + elif cmd == self.FRAME_WRITE: + frame = conn.recv_bytes() + self._writeFrame(frame) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + + def stop(self): + """ + Stop the video server. + + Releases all resources and closes any open windows. + Returns: + None + """ + self._disableStream() + if (self.mode == MODE_VIDEO_OUTPUT) and (self.filename == None): + try: + cv2.destroyAllWindows() + except Exception: + pass + self.listener.close() + logger.info("Video server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the video server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Video Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = VideoServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-310/Board-U55.clayer.yml b/board/Corstone-310/Board-U55.clayer.yml new file mode 100644 index 0000000..7445293 --- /dev/null +++ b/board/Corstone-310/Board-U55.clayer.yml @@ -0,0 +1,64 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U55 + for-board: ARM::V2M-MPS3-SSE-310 + for-device: ARM::SSE-310-MPS3_FVP + + connections: + - connect: Corstone-310 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-310.h\" + - ETHOSU55 + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-310.h diff --git a/board/Corstone-310/Board-U65.clayer.yml b/board/Corstone-310/Board-U65.clayer.yml new file mode 100644 index 0000000..ab2d117 --- /dev/null +++ b/board/Corstone-310/Board-U65.clayer.yml @@ -0,0 +1,64 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U65 + for-board: ARM::V2M-MPS3-SSE-310 + for-device: ARM::SSE-310-MPS3_FVP + + connections: + - connect: Corstone-310 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-310.h\" + - ETHOSU65 + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U65 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-310.h diff --git a/board/Corstone-310/Board.clayer.yml b/board/Corstone-310/Board.clayer.yml new file mode 100644 index 0000000..dd053ff --- /dev/null +++ b/board/Corstone-310/Board.clayer.yml @@ -0,0 +1,59 @@ +layer: + type: Board + description: Board setup for AI/ML + for-board: ARM::V2M-MPS3-SSE-310 + for-device: ARM::SSE-310-MPS3_FVP + + connections: + - connect: Corstone-310 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-310.h\" + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::AVH_FVP + - pack: ARM::V2M_MPS3_SSE_310_BSP@1.4.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-310.h diff --git a/board/Corstone-310/Corstone-310.h b/board/Corstone-310/Corstone-310.h new file mode 100644 index 0000000..2047ff8 --- /dev/null +++ b/board/Corstone-310/Corstone-310.h @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef CORSTONE_310_H_ +#define CORSTONE_310_H_ + +#include "Driver_USART.h" +#include "cmsis_vstream.h" + +// CMSIS Driver instances of Board peripherals +#define CMSIS_DRIVER_USART 0 // CMSIS Driver USART instance number + +// Retarget stdio to CMSIS UART +#define RETARGET_STDIO_UART 0 + +// CMSIS Drivers +extern ARM_DRIVER_USART Driver_USART0; /* Serial */ +extern vStreamDriver_t Driver_vStreamAudioIn; /* Audio In Stream */ +extern vStreamDriver_t Driver_vStreamAudioOut; /* Audio Out Stream */ +extern vStreamDriver_t Driver_vStreamVideoIn; /* Video In Stream */ +extern vStreamDriver_t Driver_vStreamVideoOut; /* Video Out Stream */ + +#ifdef CMSIS_shield_header +#include CMSIS_shield_header +#endif + +#endif /* CORSTONE_310_H_ */ diff --git a/board/Corstone-310/README.md b/board/Corstone-310/README.md new file mode 100644 index 0000000..5470063 --- /dev/null +++ b/board/Corstone-310/README.md @@ -0,0 +1,35 @@ +# Board: Arm V2M-MPS3-SSE-310 + +## Board Layer for Corstone-310 FVP + +Device: SSE-310-MPS3_FVP + +### System Configuration + +| System Component | Setting +|:------------------------|:---------------------------------- +| Heap | 768 kB (configured in linker file) +| Stack (MSP) | 32 kB (configured in linker file) + +### STDIO mapping + +**STDIO** is routed to terminal via **UART0** peripheral + +### CMSIS-Driver mapping + +| CMSIS-Driver | Peripheral | Connection +|:-----------------------|:-----------|:---------------------- +| Driver_USART0 | UART0 | STDOUT, STDERR +| Driver_vStreamAudioIn | VSI0 | CMSIS_VSTREAM_AUDIO_IN +| Driver_vStreamAudioOut | VSI1 | CMSIS_VSTREAM_AUDIO_OUT +| Driver_vStreamVideoIn | VSI4 | CMSIS_VSTREAM_VIDEO_IN +| Driver_vStreamVideoOut | VSI6 | CMSIS_VSTREAM_VIDEO_OUT + +### CMSIS-Driver vStream configuration + +| Driver | Stream Format Description +|:-----------------------|:---------------------------------------------------- +| 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) diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h new file mode 100644 index 0000000..fd1d7d0 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 new file mode 100644 index 0000000..a4e79fe --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h new file mode 100644 index 0000000..da9aa7e --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 new file mode 100644 index 0000000..b59bf69 --- /dev/null +++ b/board/Corstone-310/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src new file mode 100644 index 0000000..ac2c3c6 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/ac6_linker_script.sct.src @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE 8 +#else +#define __STACKSEAL_SIZE 0 +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + + ER_ROM0 __ROM0_BASE __ROM0_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + *(+RO +XO) + } + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) { + *(Veneer$$CMSE) + } +#endif + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) { + *.o(.bss.noinit) + *.o(.bss.noinit.*) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#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) + + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM1_SIZE > 0 +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + ER_ROM1 +0 __ROM1_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + ; NN Model Binary Representation + *.o (nn_model) + + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h new file mode 100644 index 0000000..af47122 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 310 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN0_S +#define PPC_CORSTONE310_MAIN0_DEV PPC_CORSTONE310_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP0_S +#define PPC_CORSTONE310_MAIN_EXP0_DEV PPC_CORSTONE310_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP1_S +#define PPC_CORSTONE310_MAIN_EXP1_DEV PPC_CORSTONE310_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP2_S +#define PPC_CORSTONE310_MAIN_EXP2_DEV PPC_CORSTONE310_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP3_S +#define PPC_CORSTONE310_MAIN_EXP3_DEV PPC_CORSTONE310_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH0_S +#define PPC_CORSTONE310_PERIPH0_DEV PPC_CORSTONE310_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH1_S +#define PPC_CORSTONE310_PERIPH1_DEV PPC_CORSTONE310_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP0_S +#define PPC_CORSTONE310_PERIPH_EXP0_DEV PPC_CORSTONE310_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP1_S +#define PPC_CORSTONE310_PERIPH_EXP1_DEV PPC_CORSTONE310_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP2_S +#define PPC_CORSTONE310_PERIPH_EXP2_DEV PPC_CORSTONE310_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP3_S +#define PPC_CORSTONE310_PERIPH_EXP3_DEV PPC_CORSTONE310_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h.base@1.1.0 b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h.base@1.1.0 new file mode 100644 index 0000000..af47122 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/device_cfg.h.base@1.1.0 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 310 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN0_S +#define PPC_CORSTONE310_MAIN0_DEV PPC_CORSTONE310_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP0_S +#define PPC_CORSTONE310_MAIN_EXP0_DEV PPC_CORSTONE310_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP1_S +#define PPC_CORSTONE310_MAIN_EXP1_DEV PPC_CORSTONE310_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP2_S +#define PPC_CORSTONE310_MAIN_EXP2_DEV PPC_CORSTONE310_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE310 +#define PPC_CORSTONE310_MAIN_EXP3_S +#define PPC_CORSTONE310_MAIN_EXP3_DEV PPC_CORSTONE310_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH0_S +#define PPC_CORSTONE310_PERIPH0_DEV PPC_CORSTONE310_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH1_S +#define PPC_CORSTONE310_PERIPH1_DEV PPC_CORSTONE310_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP0_S +#define PPC_CORSTONE310_PERIPH_EXP0_DEV PPC_CORSTONE310_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP1_S +#define PPC_CORSTONE310_PERIPH_EXP1_DEV PPC_CORSTONE310_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP2_S +#define PPC_CORSTONE310_PERIPH_EXP2_DEV PPC_CORSTONE310_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE310 +#define PPC_CORSTONE310_PERIPH_EXP3_S +#define PPC_CORSTONE310_PERIPH_EXP3_DEV PPC_CORSTONE310_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src new file mode 100644 index 0000000..3f8cf75 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/gcc_linker_script.ld.src @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + 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) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __noinit_start + * __noinit_end + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM0 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM0 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + LONG (LOADADDR(.init_buf)) + LONG (ADDR(.init_buf)) + LONG (SIZEOF(.init_buf) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM0 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM0 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM0 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM0 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit (NOLOAD) : + { + . = ALIGN(4); + __noinit_start = .; + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + __noinit_end = .; + } > RAM0 + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + /* Non-initialized buffers in fast access RAM */ + .cache (NOLOAD): + { + . = ALIGN(32); + *(*ethos_cache_buf) /* Ethos-U Cache Area */ + *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + } > RAM1 + + /* Initialized buffers in fast access RAM */ + /* Entry must exist in .copy.table */ + .init_buf : + { + /* Add objects that go into RAM1 */ + } > RAM1 AT > ROM1 + + .rom2 : + { + *(*nn_model) /* NN Model Binary Representation */ + } > ROM2 + + .rom3 : + { + /* Add objects that go into ROM3 */ + } > ROM3 +} diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src new file mode 100644 index 0000000..ea02d53 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/iar_linker_script.icf.src @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define memory mem with size = 4G; + +#if __ROM0_SIZE > 0 + define region ROM0_region = mem:[from __ROM0_BASE to (__ROM0_BASE+__ROM0_SIZE-1)]; +#else + define region ROM0_region = []; +#endif + +#if __ROM1_SIZE > 0 + define region ROM1_region = mem:[from __ROM1_BASE to (__ROM1_BASE+__ROM1_SIZE-1)]; +#else + define region ROM1_region = []; +#endif + +#if __ROM2_SIZE > 0 + define region ROM2_region = mem:[from __ROM2_BASE to (__ROM2_BASE+__ROM2_SIZE-1)]; +#else + define region ROM2_region = []; +#endif + +#if __ROM3_SIZE > 0 + define region ROM3_region = mem:[from __ROM3_BASE to (__ROM3_BASE+__ROM3_SIZE-1)]; +#else + 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 + define region RAM0_region = []; +#endif + +#if __RAM1_SIZE > 0 + define region RAM1_region = mem:[from __RAM1_BASE to (__RAM1_BASE+__RAM1_SIZE-1)]; +#else + define region RAM1_region = []; +#endif + +#if __RAM2_SIZE > 0 + define region RAM2_region = mem:[from __RAM2_BASE to (__RAM2_BASE+__RAM2_SIZE-1)]; +#else + define region RAM2_region = []; +#endif + +#if __RAM3_SIZE > 0 + define region RAM3_region = mem:[from __RAM3_BASE to (__RAM3_BASE+__RAM3_SIZE-1)]; +#else + 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)) +{ + // Required in a multi-threaded application + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +place at address mem:__ROM0_BASE { readonly section .intvec }; + +if (!isempty(ROM_region)) +{ + place in ROM_region { readonly }; +} + +if (!isempty(RAM_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 }; +} diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c new file mode 100644 index 0000000..5d0b5ae --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2022-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE310MPS3.h" +#include "system_SSE310MPS3.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +#ifdef CORSTONE310_FVP +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +#else +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Combined_Handler) +#endif +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Combined_Handler) +#ifdef CORSTONE310_FVP +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) +#endif + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + 0, /* 15: Reserved */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + 0, /* 26: Reserved */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + 0, /* 56: Reserved */ +#ifdef CORSTONE310_FVP + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ +#else + DMA_Ch_0_Error_Handler, /* 57: DMA Ch0 Error Handler */ + DMA_Ch_0_Terminal_Count_Handler, /* 58: DMA Ch0 Terminal Count Handler */ + DMA_Ch_0_Combined_Handler, /* 59: DMA Ch0 Combined Handler */ + DMA_Ch_1_Error_Handler, /* 60: DMA Ch1 Error Handler */ + DMA_Ch_1_Terminal_Count_Handler, /* 61: DMA Ch1 Terminal Count Handler */ + DMA_Ch_1_Combined_Handler, /* 62: DMA Ch1 Combined Handler */ + DMA_Ch_2_Error_Handler, /* 63: DMA Ch2 Error Handler */ + DMA_Ch_2_Terminal_Count_Handler, /* 64: DMA Ch2 Terminal Count Handler */ + DMA_Ch_2_Combined_Handler, /* 65: DMA Ch2 Combined Handler */ + DMA_Ch_3_Error_Handler, /* 66: DMA Ch3 Error Handler */ + DMA_Ch_3_Terminal_Count_Handler, /* 67: DMA Ch3 Terminal Count Handler */ + DMA_Ch_3_Combined_Handler, /* 68: DMA Ch3 Combined Handler */ +#endif + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Combined_Handler, /* 127: UART 5 combined Interrupt */ +#ifdef CORSTONE310_FVP + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + 0, /* 132: Reserved */ + 0, /* 133: Reserved */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +#endif +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c.base@1.1.0 b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c.base@1.1.0 new file mode 100644 index 0000000..5d0b5ae --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/startup_SSE310MPS3.c.base@1.1.0 @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2022-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE310MPS3.h" +#include "system_SSE310MPS3.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(DEBUG_PPU_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(TOUCH_SCREEN_Handler) +DEFAULT_IRQ_HANDLER(USB_Handler) +DEFAULT_IRQ_HANDLER(SPI_ADC_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD0_Handler) +DEFAULT_IRQ_HANDLER(SPI_SHIELD1_Handler) +#ifdef CORSTONE310_FVP +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +#else +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_0_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_1_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_2_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Error_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Terminal_Count_Handler) +DEFAULT_IRQ_HANDLER(DMA_Ch_3_Combined_Handler) +#endif +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_3_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_4_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_5_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_6_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_7_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_8_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_9_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_10_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_11_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_12_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_13_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_14_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_15_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_0_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_1_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_2_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(UART5_Combined_Handler) +#ifdef CORSTONE310_FVP +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) +#endif + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + 0, /* 15: Reserved */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + 0, /* 20: Reserved */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + 0, /* 24: Reserved */ + 0, /* 25: Reserved */ + 0, /* 26: Reserved */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + 0, /* 30: Reserved */ + 0, /* 31: Reserved */ + + /* External interrupts */ + System_Timestamp_Counter_Handler, /* 32: System timestamp counter Handler */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + TOUCH_SCREEN_Handler, /* 51: Touch Screen Handler */ + USB_Handler, /* 52: USB Handler */ + SPI_ADC_Handler, /* 53: SPI ADC Handler */ + SPI_SHIELD0_Handler, /* 54: SPI (Shield 0) Handler */ + SPI_SHIELD1_Handler, /* 55: SPI (Shield 0) Handler */ + 0, /* 56: Reserved */ +#ifdef CORSTONE310_FVP + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ +#else + DMA_Ch_0_Error_Handler, /* 57: DMA Ch0 Error Handler */ + DMA_Ch_0_Terminal_Count_Handler, /* 58: DMA Ch0 Terminal Count Handler */ + DMA_Ch_0_Combined_Handler, /* 59: DMA Ch0 Combined Handler */ + DMA_Ch_1_Error_Handler, /* 60: DMA Ch1 Error Handler */ + DMA_Ch_1_Terminal_Count_Handler, /* 61: DMA Ch1 Terminal Count Handler */ + DMA_Ch_1_Combined_Handler, /* 62: DMA Ch1 Combined Handler */ + DMA_Ch_2_Error_Handler, /* 63: DMA Ch2 Error Handler */ + DMA_Ch_2_Terminal_Count_Handler, /* 64: DMA Ch2 Terminal Count Handler */ + DMA_Ch_2_Combined_Handler, /* 65: DMA Ch2 Combined Handler */ + DMA_Ch_3_Error_Handler, /* 66: DMA Ch3 Error Handler */ + DMA_Ch_3_Terminal_Count_Handler, /* 67: DMA Ch3 Terminal Count Handler */ + DMA_Ch_3_Combined_Handler, /* 68: DMA Ch3 Combined Handler */ +#endif + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + GPIO0_0_Handler, /* 73: GPIO0 Pin 0 Handler */ + GPIO0_1_Handler, /* 74: GPIO0 Pin 1 Handler */ + GPIO0_2_Handler, /* 75: GPIO0 Pin 2 Handler */ + GPIO0_3_Handler, /* 76: GPIO0 Pin 3 Handler */ + GPIO0_4_Handler, /* 77: GPIO0 Pin 4 Handler */ + GPIO0_5_Handler, /* 78: GPIO0 Pin 5 Handler */ + GPIO0_6_Handler, /* 79: GPIO0 Pin 6 Handler */ + GPIO0_7_Handler, /* 80: GPIO0 Pin 7 Handler */ + GPIO0_8_Handler, /* 81: GPIO0 Pin 8 Handler */ + GPIO0_9_Handler, /* 82: GPIO0 Pin 9 Handler */ + GPIO0_10_Handler, /* 83: GPIO0 Pin 10 Handler */ + GPIO0_11_Handler, /* 84: GPIO0 Pin 11 Handler */ + GPIO0_12_Handler, /* 85: GPIO0 Pin 12 Handler */ + GPIO0_13_Handler, /* 86: GPIO0 Pin 13 Handler */ + GPIO0_14_Handler, /* 87: GPIO0 Pin 14 Handler */ + GPIO0_15_Handler, /* 88: GPIO0 Pin 15 Handler */ + GPIO1_0_Handler, /* 89: GPIO1 Pin 0 Handler */ + GPIO1_1_Handler, /* 90: GPIO1 Pin 1 Handler */ + GPIO1_2_Handler, /* 91: GPIO1 Pin 2 Handler */ + GPIO1_3_Handler, /* 92: GPIO1 Pin 3 Handler */ + GPIO1_4_Handler, /* 93: GPIO1 Pin 4 Handler */ + GPIO1_5_Handler, /* 94: GPIO1 Pin 5 Handler */ + GPIO1_6_Handler, /* 95: GPIO1 Pin 6 Handler */ + GPIO1_7_Handler, /* 96: GPIO1 Pin 7 Handler */ + GPIO1_8_Handler, /* 97: GPIO1 Pin 8 Handler */ + GPIO1_9_Handler, /* 98: GPIO1 Pin 9 Handler */ + GPIO1_10_Handler, /* 99: GPIO1 Pin 10 Handler */ + GPIO1_11_Handler, /* 100: GPIO1 Pin 11 Handler */ + GPIO1_12_Handler, /* 101: GPIO1 Pin 12 Handler */ + GPIO1_13_Handler, /* 102: GPIO1 Pin 13 Handler */ + GPIO1_14_Handler, /* 103: GPIO1 Pin 14 Handler */ + GPIO1_15_Handler, /* 104: GPIO1 Pin 15 Handler */ + GPIO2_0_Handler, /* 105: GPIO2 Pin 0 Handler */ + GPIO2_1_Handler, /* 106: GPIO2 Pin 1 Handler */ + GPIO2_2_Handler, /* 107: GPIO2 Pin 2 Handler */ + GPIO2_3_Handler, /* 108: GPIO2 Pin 3 Handler */ + GPIO2_4_Handler, /* 109: GPIO2 Pin 4 Handler */ + GPIO2_5_Handler, /* 110: GPIO2 Pin 5 Handler */ + GPIO2_6_Handler, /* 111: GPIO2 Pin 6 Handler */ + GPIO2_7_Handler, /* 112: GPIO2 Pin 7 Handler */ + GPIO2_8_Handler, /* 113: GPIO2 Pin 8 Handler */ + GPIO2_9_Handler, /* 114: GPIO2 Pin 9 Handler */ + GPIO2_10_Handler, /* 115: GPIO2 Pin 10 Handler */ + GPIO2_11_Handler, /* 116: GPIO2 Pin 11 Handler */ + GPIO2_12_Handler, /* 117: GPIO2 Pin 12 Handler */ + GPIO2_13_Handler, /* 118: GPIO2 Pin 13 Handler */ + GPIO2_14_Handler, /* 119: GPIO2 Pin 14 Handler */ + GPIO2_15_Handler, /* 120: GPIO2 Pin 15 Handler */ + GPIO3_0_Handler, /* 121: GPIO3 Pin 0 Handler */ + GPIO3_1_Handler, /* 122: GPIO3 Pin 1 Handler */ + GPIO3_2_Handler, /* 123: GPIO3 Pin 2 Handler */ + GPIO3_3_Handler, /* 124: GPIO3 Pin 3 Handler */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + UART5_Combined_Handler, /* 127: UART 5 combined Interrupt */ +#ifdef CORSTONE310_FVP + 0, /* 128: Reserved */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + 0, /* 132: Reserved */ + 0, /* 133: Reserved */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +#endif +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c new file mode 100644 index 0000000..d19e9e2 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE310MPS3.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c.base@1.1.0 b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c.base@1.1.0 new file mode 100644 index 0000000..d19e9e2 --- /dev/null +++ b/board/Corstone-310/RTE/Device/SSE-310-MPS3_FVP/system_SSE310MPS3.c.base@1.1.0 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE310MPS3.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-310/ethos_setup.c b/board/Corstone-310/ethos_setup.c new file mode 100644 index 0000000..ca26dfa --- /dev/null +++ b/board/Corstone-310/ethos_setup.c @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + + #include + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "ethosu_driver.h" +#include "main.h" + +#if defined(ETHOSU65) || defined(ETHOSU85) +/* Define Ethos-U NPU cache buffer size */ +#ifndef ETHOS_CACHE_BUF_SIZE +#define ETHOS_CACHE_BUF_SIZE 393216 +#endif + +/* Define Ethos-U cache buffer alignment */ +#ifndef ETHOS_CACHE_BUF_ALIGNMENT +#define ETHOS_CACHE_BUF_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))) +#endif +#endif + +/* Define Ethos-U NPU security mode */ +#ifndef ETHOS_SECURE_ENABLE +#define ETHOS_SECURE_ENABLE 1 +#endif + +/* Define Ethos-U NPU privilege mode */ +#ifndef ETHOS_PRIVILEGE_ENABLE +#define ETHOS_PRIVILEGE_ENABLE 1 +#endif + +/* 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; +#endif + +/* + Ethos NPU interrupt handler. +*/ +void NPU0_Handler(void) { + ethosu_irq_handler(&EthosDriver); +} + +/* + Initialize the Ethos NPU driver. +*/ +void ethos_setup (void) { + void * const ethos_base_addr = (void *)NPU0_APB_BASE_S; + struct ethosu_hw_info hw_info; + int rval; + + /* 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 */ + #else + 0, /* Cache memory pointer */ + 0, /* Cache memory size */ + #endif + ETHOS_SECURE_ENABLE, /* Secure enable */ + ETHOS_PRIVILEGE_ENABLE); /* Privileged mode */ + if (rval != 0) { + printf("Failed to initialize Arm Ethos-U driver\n"); + } + else { + NVIC_EnableIRQ(NPU0_IRQn); + + ethosu_get_hw_info(&EthosDriver, &hw_info); + + printf("Ethos-U version info:\n"); + printf("\tArch: v%u.%u.%u\n", hw_info.version.arch_major_rev, + hw_info.version.arch_minor_rev, + hw_info.version.arch_patch_rev); + printf("\tMACs/cc: %u\n", (uint32_t)(1 << hw_info.cfg.macs_per_cc)); + printf("\tCmd stream: v%u\n", hw_info.cfg.cmd_stream_version); + } +} diff --git a/board/Corstone-310/fvp_config.txt b/board/Corstone-310/fvp_config.txt new file mode 100644 index 0000000..60f234c --- /dev/null +++ b/board/Corstone-310/fvp_config.txt @@ -0,0 +1,8 @@ +# 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). : [0x20:0x100] +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/board/Corstone-310/main.c b/board/Corstone-310/main.c new file mode 100644 index 0000000..69b3485 --- /dev/null +++ b/board/Corstone-310/main.c @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "main.h" + +int main (void) { + + /* Initialize STDIO */ + stdio_init(); + + #if defined(ETHOSU_ARCH) + /* Initialize Ethos NPU */ + ethos_setup(); + #endif + + return (app_main()); +} diff --git a/board/Corstone-310/main.h b/board/Corstone-310/main.h new file mode 100644 index 0000000..6e2048e --- /dev/null +++ b/board/Corstone-310/main.h @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2020-2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef MAIN_H__ +#define MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototypes */ +extern int app_main (void); +extern int stdio_init (void); + +#if defined(ETHOSU_ARCH) +extern void ethos_setup (void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/Corstone-310/regions_SSE-310.h b/board/Corstone-310/regions_SSE-310.h new file mode 100644 index 0000000..ec1f9b2 --- /dev/null +++ b/board/Corstone-310/regions_SSE-310.h @@ -0,0 +1,115 @@ +#ifndef REGIONS_SSE_310_H +#define REGIONS_SSE_310_H + +#include "sse310_memmap_s.h" +#include "sse310_memmap_ns.h" + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// ROM Configuration +// ======================= +// __ROM0 +// Base address +// Defines base address of memory region. +// Contains Startup and Vector Table +// Default: FPGA_SRAM_S_BASE +#define __ROM0_BASE FPGA_SRAM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: FPGA_SRAM_S_SIZE +#define __ROM0_SIZE FPGA_SRAM_S_SIZE +// + +// __ROM1 +// Base address +// Defines base address of memory region. +// Default: ITCM_S_BASE +#define __ROM1_BASE ITCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: ITCM_S_SIZE +#define __ROM1_SIZE ITCM_S_SIZE +// + +// __ROM2 +// Base address +// Defines base address of memory region. +// Default: DDR4_3_S_BASE +#define __ROM2_BASE DDR4_3_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_3_S_SIZE +#define __ROM2_SIZE DDR4_3_S_SIZE +// + +// __ROM3 +// Base address +// Defines base address of memory region. +// Default: QSPI_FLASH_S_BASE +#define __ROM3_BASE QSPI_FLASH_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: QSPI_FLASH_S_SIZE +#define __ROM3_SIZE QSPI_FLASH_S_SIZE +// + +// + +// RAM Configuration +// ======================= +// __RAM0 +// Base address +// Defines base address of memory region. +// Default: DDR4_1_S_BASE +#define __RAM0_BASE DDR4_1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_1_S_SIZE +#define __RAM0_SIZE DDR4_1_S_SIZE +// + +// __RAM1 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM0_S_BASE +#define __RAM1_BASE SRAM_VM0_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM0_S_SIZE +#define __RAM1_SIZE SRAM_VM0_S_SIZE +// + +// __RAM2 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM1_S_BASE +#define __RAM2_BASE SRAM_VM1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM1_S_SIZE +#define __RAM2_SIZE SRAM_VM1_S_SIZE +// + +// __RAM3 +// Base address +// Defines base address of memory region. +// Default: DTCM_S_BASE +#define __RAM3_BASE DTCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DTCM_S_SIZE +#define __RAM3_SIZE DTCM_S_SIZE +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00001000 +#define __HEAP_SIZE 0x00018000 +// + +#endif /* REGIONS_SSE_310_H */ diff --git a/board/Corstone-310/retarget_stdio.c b/board/Corstone-310/retarget_stdio.c new file mode 100644 index 0000000..f553eed --- /dev/null +++ b/board/Corstone-310/retarget_stdio.c @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Name: retarget_stdio.c + * Purpose: Retarget stdio to CMSIS UART + * + *---------------------------------------------------------------------------*/ + +#ifdef CMSIS_target_header +#include CMSIS_target_header +#else +#include "Driver_USART.h" +#endif + +#ifndef RETARGET_STDIO_UART +#error "RETARGET_STDIO_UART not defined!" +#endif + +/* Compile-time configuration */ +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif + +/* References to the external retarget functions */ +extern int stdio_init (void); +extern int stderr_putchar (int ch); +extern int stdout_putchar (int ch); +extern int stdin_getchar (void); + +/* Reference to the underlying USART driver */ +#ifndef CMSIS_target_header +extern ARM_DRIVER_USART ARM_Driver_USART_(RETARGET_STDIO_UART); +#endif +#define ptrUSART (&ARM_Driver_USART_(RETARGET_STDIO_UART)) + +/** + Initialize stdio + + \return 0 on success, or -1 on error. +*/ +int stdio_init (void) { + + if (ptrUSART->Initialize(NULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | + ARM_USART_DATA_BITS_8 | + ARM_USART_PARITY_NONE | + ARM_USART_STOP_BITS_1 | + ARM_USART_FLOW_CONTROL_NONE, + UART_BAUDRATE) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_RX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_TX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + return 0; +} + +/** + Put a character to the stderr + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stderr_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Put a character to the stdout + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stdout_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Get a character from the stdio + + \return The next character from the input, or -1 on read error. +*/ +int stdin_getchar (void) { + uint8_t buf[1]; + + if (ptrUSART->Receive(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().rx_busy != 0U); + + return (int)buf[0]; +} \ No newline at end of file diff --git a/board/Corstone-310/sse310_memmap_ns.h b/board/Corstone-310/sse310_memmap_ns.h new file mode 100644 index 0000000..af37d33 --- /dev/null +++ b/board/Corstone-310/sse310_memmap_ns.h @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE310_MEMMAP_NS_H +#define SSE310_MEMMAP_NS_H + +/*============================================================================*/ +/* NON-SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Non-Secure */ +#define ITCM_NS_BASE 0x00000000 +#define ITCM_NS_SIZE 0x00008000 /* 32KB */ +#define ITCM_NS_LIMIT (ITCM_NS_BASE + ITCM_NS_SIZE - 1) + +/* FPGA SRAM - Non-Secure */ +#define FPGA_SRAM_NS_BASE 0x01000000 +#define FPGA_SRAM_NS_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_NS_LIMIT (FPGA_SRAM_NS_BASE + FPGA_SRAM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Non-Secure */ +#define DTCM_NS_BASE 0x20000000 +#define DTCM_NS_SIZE 0x00008000 /* 32KB */ +#define DTCM_NS_LIMIT (DTCM_NS_BASE + DTCM_NS_SIZE - 1) + +/* SRAM VM0 - Non-Secure */ +#define SRAM_VM0_NS_BASE 0x21000000 +#define SRAM_VM0_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_NS_LIMIT (SRAM_VM0_NS_BASE + SRAM_VM0_NS_SIZE - 1) + +/* SRAM VM1 - Non-Secure */ +#define SRAM_VM1_NS_BASE 0x21200000 +#define SRAM_VM1_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_NS_LIMIT (SRAM_VM1_NS_BASE + SRAM_VM1_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_NS_BASE 0x28000000 +#define QSPI_FLASH_NS_SIZE 0x00800000 /* 8MB */ +#define QSPI_FLASH_NS_LIMIT (QSPI_FLASH_NS_BASE + QSPI_FLASH_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 0 - Non-Secure */ +#define DDR4_0_NS_BASE 0x60000000 +#define DDR4_0_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_0_NS_LIMIT (DDR4_0_NS_BASE + DDR4_0_NS_SIZE - 1) + +/* DDR4 Region 2 - Non-Secure */ +#define DDR4_2_NS_BASE 0x80000000 +#define DDR4_2_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_2_NS_LIMIT (DDR4_2_NS_BASE + DDR4_2_NS_SIZE - 1) + +/* DDR4 Region 4 - Non-Secure */ +#define DDR4_4_NS_BASE 0xA0000000 +#define DDR4_4_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_4_NS_LIMIT (DDR4_4_NS_BASE + DDR4_4_NS_SIZE - 1) + +/* DDR4 Region 6 - Non-Secure */ +#define DDR4_6_NS_BASE 0xC0000000 +#define DDR4_6_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_6_NS_LIMIT (DDR4_6_NS_BASE + DDR4_6_NS_SIZE - 1) + +#endif /* SSE310_MEMMAP_NS_H */ diff --git a/board/Corstone-310/sse310_memmap_s.h b/board/Corstone-310/sse310_memmap_s.h new file mode 100644 index 0000000..ce05c23 --- /dev/null +++ b/board/Corstone-310/sse310_memmap_s.h @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE310_MEMMAP_S_H +#define SSE310_MEMMAP_S_H + +/*============================================================================*/ +/* SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Secure */ +#define ITCM_S_BASE 0x10000000 +#define ITCM_S_SIZE 0x00008000 /* 32KB */ +#define ITCM_S_LIMIT (ITCM_S_BASE + ITCM_S_SIZE - 1) + +/* FPGA SRAM - Secure (Startup) */ +#define FPGA_SRAM_S_BASE 0x11000000 +#define FPGA_SRAM_S_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_S_LIMIT (FPGA_SRAM_S_BASE + FPGA_SRAM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Secure */ +#define DTCM_S_BASE 0x30000000 +#define DTCM_S_SIZE 0x00008000 /* 32KB */ +#define DTCM_S_LIMIT (DTCM_S_BASE + DTCM_S_SIZE - 1) + +/* SRAM VM0 - Secure */ +#define SRAM_VM0_S_BASE 0x31000000 +#define SRAM_VM0_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_S_LIMIT (SRAM_VM0_S_BASE + SRAM_VM0_S_SIZE - 1) + +/* SRAM VM1 - Secure */ +#define SRAM_VM1_S_BASE 0x31200000 +#define SRAM_VM1_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_S_LIMIT (SRAM_VM1_S_BASE + SRAM_VM1_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_S_BASE 0x38000000 +#define QSPI_FLASH_S_SIZE 0x00800000 /* 8MB */ +#define QSPI_FLASH_S_LIMIT (QSPI_FLASH_S_BASE + QSPI_FLASH_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 1 - Secure */ +#define DDR4_1_S_BASE 0x70000000 +#define DDR4_1_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_1_S_LIMIT (DDR4_1_S_BASE + DDR4_1_S_SIZE - 1) + +/* DDR4 Region 3 - Secure */ +#define DDR4_3_S_BASE 0x90000000 +#define DDR4_3_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_3_S_LIMIT (DDR4_3_S_BASE + DDR4_3_S_SIZE - 1) + +/* DDR4 Region 5 - Secure */ +#define DDR4_5_S_BASE 0xB0000000 +#define DDR4_5_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_5_S_LIMIT (DDR4_5_S_BASE + DDR4_5_S_SIZE - 1) + +/* DDR4 Region 7 - Secure */ +#define DDR4_7_S_BASE 0xD0000000 +#define DDR4_7_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_7_S_LIMIT (DDR4_7_S_BASE + DDR4_7_S_SIZE - 1) + +#endif /* SSE310_MEMMAP_S_H */ diff --git a/board/Corstone-310/vsi/python/arm_vsi0.py b/board/Corstone-310/vsi/python/arm_vsi0.py new file mode 100644 index 0000000..e1a7bfc --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi0.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 0 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi0_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6000) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/arm_vsi1.py b/board/Corstone-310/vsi/python/arm_vsi1.py new file mode 100644 index 0000000..f1271b5 --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi1.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 1 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi1_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6001) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/arm_vsi4.py b/board/Corstone-310/vsi/python/arm_vsi4.py new file mode 100644 index 0000000..e15edf8 --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi4.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 4 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi4_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6004) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/arm_vsi5.py b/board/Corstone-310/vsi/python/arm_vsi5.py new file mode 100644 index 0000000..631f74d --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi5.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 5 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi5_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6005) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/arm_vsi6.py b/board/Corstone-310/vsi/python/arm_vsi6.py new file mode 100644 index 0000000..58b1184 --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi6.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 6 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi6_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6006) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/arm_vsi7.py b/board/Corstone-310/vsi/python/arm_vsi7.py new file mode 100644 index 0000000..cd32ab8 --- /dev/null +++ b/board/Corstone-310/vsi/python/arm_vsi7.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 7 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi7_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6007) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-310/vsi/python/vsi_audio.py b/board/Corstone-310/vsi/python/vsi_audio.py new file mode 100644 index 0000000..a71574a --- /dev/null +++ b/board/Corstone-310/vsi/python/vsi_audio.py @@ -0,0 +1,543 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) audio server. +# It allows configuration, streaming, and audio data transfer operations, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Audio:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Audio:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class AudioClient: + """ + Client for communicating with the VSI audio server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive audio data, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Audio format codes + self.PCM_S8 = 0 + self.PCM_S16LE = 1 + self.PCM_S24LE = 2 + self.PCM_S32LE = 3 + self.PCM_F32LE = 4 + + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI audio server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the audio stream (input/output). + Args: + mode: 1 for input, 2 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the audio streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the audio stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters on the server. + Args: + channels: Number of audio channels (1=mono, 2=stereo). + sample_rate: Sample rate in Hz (e.g., 44100, 48000). + sample_bits: Bit depth (8, 16, 24, 32). + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, channels, sample_rate, sample_bits]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the audio stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the audio stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readAudio(self, size): + """ + Request audio data from the server. + Args: + size: Number of bytes to read. + Returns: + tuple: (data, eos) where data is a Bytearray of audio data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.AUDIO_READ, size]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeAudio(self, data): + """ + Send audio data to the server. + Args: + data: Bytearray of audio data to write. + Returns: + None + """ + self.conn.send([self.AUDIO_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +CHANNELS = 1 # Regs[4] // Number of audio channels +SAMPLE_RATE = 16000 # Regs[5] // Sample rate +SAMPLE_BITS = 16 # Regs[6] // Bits per sample + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Audio.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Audio.configureStream(CHANNELS, SAMPLE_RATE, SAMPLE_BITS) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Audio.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Audio.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Audio.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Audio.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = CHANNELS + elif index == 5: + value = SAMPLE_RATE + elif index == 6: + value = SAMPLE_BITS + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + CHANNELS = value + elif index == 5: + SAMPLE_RATE = value + elif index == 6: + SAMPLE_BITS = value + + return value diff --git a/board/Corstone-310/vsi/python/vsi_audio_server.py b/board/Corstone-310/vsi/python/vsi_audio_server.py new file mode 100644 index 0000000..dafa594 --- /dev/null +++ b/board/Corstone-310/vsi/python/vsi_audio_server.py @@ -0,0 +1,691 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Server module + +try: + import argparse + import ipaddress + import logging + import time + import wave + from multiprocessing.connection import Listener + from pathlib import Path + + import pyaudio + import numpy as np +except ImportError as err: + print(f"VSI:Audio:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Audio:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Audio Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6001) +default_authkey = 'vsi_audio' + +# Supported file extensions +supported_files = ['wav'] + +# Mode Input/Output +MODE_AUDIO_NONE = 0 +MODE_AUDIO_INPUT = 1 +MODE_AUDIO_OUTPUT = 2 + +class AudioServer: + """Implements a TCP server for audio streaming and sample I/O. + + Supports both audio files and microphone/speaker devices as input/output. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing audio data), and performs the requested audio + operations using PyAudio and wave modules. + """ + def __init__(self, address, authkey): + """ + Initialize the AudioServer. + + Sets up command codes, audio format constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.eos = False + self.stream = None + self.wave_file = None + self.pyaudio_obj = pyaudio.PyAudio() + self.audio_buffer = bytearray() + self.chunk_size = 1024 + + # Stream configuration + self.channels = None + self.sample_rate = None + self.sample_bits = None + + def _setMode(self, mode): + """ + Set the stream mode to input (microphone/file) or output (speakers/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_AUDIO_INPUT: + self.mode = MODE_AUDIO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_AUDIO_OUTPUT: + self.mode = MODE_AUDIO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_AUDIO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_audio_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in supported_files: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_AUDIO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_AUDIO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters. + + Args: + channels: The number of audio channels (1=mono, 2=stereo). + sample_rate: The sample rate in Hz (8000, 16000, 44100, 48000). + sample_bits: The bit depth (8, 16, 24, 32). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits}") + + if channels <= 0 or sample_rate <= 0 or sample_bits <= 0: + logger.error(f"_configureStream: invalid argument (channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits})") + return False + + if sample_bits not in [8, 16, 24, 32]: + logger.error(f"_configureStream: unsupported sample_bits={sample_bits}") + return False + + self.channels = channels + self.sample_rate = sample_rate + self.sample_bits = sample_bits + + logger.info(f"_configureStream: stream configured to {self.channels} channels, {self.sample_rate}Hz, {self.sample_bits} bits") + + return True + + def _get_pyaudio_format(self): + """Get PyAudio format based on sample bits.""" + if self.sample_bits == 8: + return pyaudio.paUInt8 + elif self.sample_bits == 16: + return pyaudio.paInt16 + elif self.sample_bits == 24: + return pyaudio.paInt24 + elif self.sample_bits == 32: + return pyaudio.paInt32 + else: + return pyaudio.paInt16 # default + + def _scan_audio_devices(self): + """ + Scan and log available audio devices, separating input and output devices. + Returns: + Default device index for the current mode. + """ + if self.pyaudio_obj is None: + logger.error(" _scan_audio_devices: PyAudio object is not initialized") + return 0 + + logger.info("=== Available Audio Devices ===") + device_count = self.pyaudio_obj.get_device_count() + + input_devices = [] + output_devices = [] + + # Scan all devices + for i in range(device_count): + try: + info = self.pyaudio_obj.get_device_info_by_index(i) + host_api_info = self.pyaudio_obj.get_host_api_info_by_index(info['hostApi']) + + device_info = { + 'index': i, + 'name': info['name'], + 'max_input_channels': info['maxInputChannels'], + 'max_output_channels': info['maxOutputChannels'], + 'default_sample_rate': info['defaultSampleRate'], + 'host_api': host_api_info['name'] + } + + # Categorize devices + if info['maxInputChannels'] > 0: + input_devices.append(device_info) + if info['maxOutputChannels'] > 0: + output_devices.append(device_info) + + except Exception as e: + logger.warning(f"Device {i}: Error reading device info - {e}") + + # Retrieve default devices + try: + default_input = self.pyaudio_obj.get_default_input_device_info() + default_output = self.pyaudio_obj.get_default_output_device_info() + except Exception as e: + logger.warning(f"Error getting default devices: {e}") + + if (self.mode == MODE_AUDIO_INPUT): + # Log input devices + logger.info("--- INPUT DEVICES ---") + if input_devices: + for device in input_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Input Channels: {device['max_input_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No input devices found") + + logger.info(f"Default Input Device: {default_input['index']} - {default_input['name']}") + + rval = default_input['index'] + + if (self.mode == MODE_AUDIO_OUTPUT): + # Log output devices + logger.debug("--- OUTPUT DEVICES ---") + if output_devices: + for device in output_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Output Channels: {device['max_output_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No output devices found") + + logger.info(f"Default Output Device: {default_output['index']} - {default_output['name']}") + + rval = default_output['index'] + + return rval + + def _audio_callback_input(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio input stream. + """ + logger.debug(f"_audio_callback_input: received {len(in_data)} bytes") + + self.audio_buffer.extend(in_data) + return (None, pyaudio.paContinue) + + def _audio_callback_output(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio output stream. + """ + logger.debug(f"_audio_callback_output: requested {frame_count} frames") + + bytes_needed = frame_count * self.channels * (self.sample_bits // 8) + if len(self.audio_buffer) >= bytes_needed: + data = bytes(self.audio_buffer[:bytes_needed]) + del self.audio_buffer[:bytes_needed] + else: + # Not enough data, return silence + data = b'\x00' * bytes_needed + return (data, pyaudio.paContinue) + + def _enableStream(self): + """ + Enable the audio stream for input (microphone/file) or output (file/speakers). + + Initializes the PyAudio stream or wave file as needed. + Returns: + None + """ + if self.mode != MODE_AUDIO_INPUT and self.mode != MODE_AUDIO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.audio_buffer.clear() + + try: + if self.filename == None: + # Use microphone/speakers + if self.pyaudio_obj is None: + logger.error("_enableStream: PyAudio object is not initialized") + return + + audio_format = self._get_pyaudio_format() + + if self.mode == MODE_AUDIO_INPUT: + logger.debug("_enableStream: use microphone for input streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + input=True, + input_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_input + ) + self.stream.start_stream() + + elif self.mode == MODE_AUDIO_OUTPUT: + logger.debug("_enableStream: use speakers for output streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + output=True, + output_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_output + ) + self.stream.start_stream() + + logger.info(f"_enableStream: audio device stream properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + else: + # Set file name string for audio file + file = str(self.filename.absolute()) + + logger.debug(f"_enableStream: use audio file: {file}") + + if self.mode == MODE_AUDIO_INPUT: + self.wave_file = wave.open(file, 'rb') + + # Verify file properties match configuration + file_channels = self.wave_file.getnchannels() + file_rate = self.wave_file.getframerate() + file_bits = self.wave_file.getsampwidth() * 8 + + if (file_channels != self.channels or file_rate != self.sample_rate or file_bits != self.sample_bits): + logger.warning(f"_enableStream: file properties ({file_channels}ch, {file_rate}Hz, {file_bits}bit) " + f"don't match configured ({self.channels}ch, {self.sample_rate}Hz, {self.sample_bits}bit)") + + logger.info(f"_enableStream: input file properties: channels={file_channels}, rate={file_rate}, bits={file_bits}") + + elif self.mode == MODE_AUDIO_OUTPUT: + self.wave_file = wave.open(file, 'wb') + self.wave_file.setnchannels(self.channels) + self.wave_file.setsampwidth(self.sample_bits // 8) + self.wave_file.setframerate(self.sample_rate) + + logger.info(f"_enableStream: output file properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + self.active = True + logger.info("_enableStream: stream enabled") + + except Exception as e: + logger.error(f"_enableStream: failed to enable stream: {e}") + self._disableStream() + + def _disableStream(self): + """ + Disable the audio stream and release resources. + + Returns: + None + """ + self.active = False + + try: + if self.stream is not None: + if self.stream.is_active(): + self.stream.stop_stream() + self.stream.close() + self.stream = None + + if self.pyaudio_obj is not None: + self.pyaudio_obj.terminate() + self.pyaudio_obj = None + + if self.wave_file is not None: + self.wave_file.close() + self.wave_file = None + + except Exception as e: + logger.error(f"_disableStream: error during cleanup: {e}") + + logger.info("_disableStream: stream disabled") + + def _readAudio(self, size): + """ + Read audio data from the current source. + + Args: + size: Number of bytes to read. + Returns: + audio_data: The read audio data as a bytearray, or empty if no data is available. + """ + logger.debug(f"_readAudio: size={size} bytes") + + audio_data = bytearray() + + if not self.active: + logger.error("_readAudio: stream not active") + return audio_data + + if self.eos: + logger.debug("_readAudio: end of stream") + return audio_data + + try: + if self.filename == None: + # Read from microphone buffer + while len(self.audio_buffer) < size: + # Wait for enough data + time.sleep(0.01) # Wait 10ms + + # Now we have enough data + audio_data = bytearray(self.audio_buffer[:size]) + del self.audio_buffer[:size] + + logger.debug(f"_readAudio: read {len(audio_data)} bytes from microphone buffer") + + else: + # Read from wave file + frames_to_read = size // (self.channels * (self.sample_bits // 8)) + frames_data = self.wave_file.readframes(frames_to_read) + + if len(frames_data) > 0: + audio_data = bytearray(frames_data) + logger.debug(f"_readAudio: read {len(audio_data)} bytes from file") + else: + self.eos = True + logger.debug("_readAudio: end of file reached") + + except Exception as e: + logger.error(f"_readAudio: error reading audio data: {e}") + + return audio_data + + def _writeAudio(self, data): + """ + Write audio data to the output destination (file or speakers). + + Args: + data: The input audio data as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeAudio: audio data size={len(data)} bytes") + + if not self.active: + logger.error("_writeAudio: stream not active") + return + + try: + if self.filename == None: + # Write to speakers buffer + self.audio_buffer.extend(data) + logger.debug("_writeAudio: added data to speaker buffer") + + else: + # Write to wave file + self.wave_file.writeframes(data) + logger.debug("_writeAudio: wrote data to file") + + except Exception as e: + logger.error(f"_writeAudio: error writing audio data: {e}") + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write audio, close server. + Sends responses or audio data as appropriate. + """ + logger.info("Audio server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.AUDIO_READ: + size = payload[0] + audio_data = self._readAudio(size) + conn.send_bytes(audio_data) + conn.send(self.eos) + + elif cmd == self.AUDIO_WRITE: + audio_data = conn.recv_bytes() + self._writeAudio(audio_data) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + def stop(self): + """ + Stop the audio server. + + Releases all resources. + Returns: + None + """ + self._disableStream() + self.listener.close() + logger.info("Audio server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the audio server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Audio Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = AudioServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-310/vsi/python/vsi_video.py b/board/Corstone-310/vsi/python/vsi_video.py new file mode 100644 index 0000000..47a2af2 --- /dev/null +++ b/board/Corstone-310/vsi/python/vsi_video.py @@ -0,0 +1,547 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) video server. +# It allows configuration, streaming, and frame transfer operations for video data, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Video:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Video:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class VideoClient: + """ + Client for communicating with the VSI video server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive frames, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space codes + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI video server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the video stream (input/output). + Args: + mode: 0 for input, 1 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the video streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the video stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, frame_width, frame_height, frame_rate, color_format): + """ + Configure the video stream parameters on the server. + Args: + frame_width: Width of the video frame. + frame_height: Height of the video frame. + frame_rate: Frame rate in frames per second. + color_format: Color format code. + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, frame_width, frame_height, frame_rate, color_format]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the video stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the video stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readFrame(self): + """ + Request a video frame from the server. + Returns: + tuple: (data, eos) where data is a Bytearray of frame data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.FRAME_READ]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeFrame(self, data): + """ + Send a video frame to the server. + Args: + data: Bytearray of frame data to write. + Returns: + None + """ + self.conn.send([self.FRAME_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +FRAME_WIDTH = 300 # Regs[4] // Requested frame width +FRAME_HEIGHT = 300 # Regs[5] // Requested frame height +FRAME_RATE = 0 # Regs[6] // Frame rate +FRAME_COLOR = 0 # Regs[7] // Frame color space + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Video.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Video.configureStream(FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Video.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Video.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Video.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Video.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = FRAME_WIDTH + elif index == 5: + value = FRAME_HEIGHT + elif index == 6: + value = FRAME_RATE + elif index == 7: + value = FRAME_COLOR + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + FRAME_WIDTH = value + elif index == 5: + FRAME_HEIGHT = value + elif index == 6: + FRAME_RATE = value + elif index == 7: + FRAME_COLOR = value + + return value diff --git a/board/Corstone-310/vsi/python/vsi_video_server.py b/board/Corstone-310/vsi/python/vsi_video_server.py new file mode 100644 index 0000000..3699eb3 --- /dev/null +++ b/board/Corstone-310/vsi/python/vsi_video_server.py @@ -0,0 +1,785 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Server module + +try: + import argparse + import ipaddress + import logging + from multiprocessing.connection import Listener + from pathlib import Path + + import cv2 + import numpy as np +except ImportError as err: + print(f"VSI:Video:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Video:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Video Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6000) +default_authkey = 'vsi_video' + +# Supported file extensions +video_file_extensions = ('wmv', 'avi', 'mp4') +image_file_extensions = ('bmp', 'png', 'jpg') +video_fourcc = {'wmv' : 'WMV1', 'avi' : 'MJPG', 'mp4' : 'mp4v'} + +# Mode Input/Output +MODE_VIDEO_NONE = 0 +MODE_VIDEO_INPUT = 1 +MODE_VIDEO_OUTPUT = 2 + +class VideoServer: + """Implements a TCP server for video streaming and frame I/O. + + Supports both video and image files as input/output, and can interface with a camera device. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing frames), and performs the requested video + operations using OpenCV. + """ + def __init__(self, address, authkey): + """ + Initialize the VideoServer. + + Sets up command codes, color space constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.video = True + self.stream = None + self.frame_ratio = 0 + self.frame_drop = 0 + self.eos = False + # Stream configuration + self.frame_width = None + self.frame_height = None + self.frame_color = None + self.frame_rate = None + + + def _setMode(self, mode): + """ + Set the stream mode to input (camera/file) or output (display/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_VIDEO_INPUT: + self.mode = MODE_VIDEO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_VIDEO_OUTPUT: + self.mode = MODE_VIDEO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_VIDEO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_video_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in video_file_extensions + image_file_extensions: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_VIDEO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_VIDEO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, frame_width, frame_height, frame_rate, frame_color): + """ + Configure the video stream parameters. + + Args: + frame_width: The desired frame width in pixels. + frame_height: The desired frame height in pixels. + frame_rate: The desired frame rate in frames per second. + frame_color: The desired frame color space (one of the defined constants). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: frame_width={frame_width}, frame_height={frame_height}, frame_rate={frame_rate}, frame_color={frame_color}") + + if (frame_width == 0 or frame_height == 0 or frame_rate == 0): + logger.error(f"_configureStream: invalid argument (width={frame_width}, height={frame_height}, rate={frame_rate})") + return False + if frame_color not in (self.GRAYSCALE8, self.RGB888, self.BGR565, self.YUV420, self.NV12, self.NV21): + logger.error(f"_configureStream: invalid argument (color={frame_color})") + return False + + self.frame_width = frame_width + self.frame_height = frame_height + self.frame_rate = frame_rate + self.frame_color = frame_color + + logger.info(f"_configureStream: stream configured to {self.frame_width}x{self.frame_height}, fps={self.frame_rate}, color={self.frame_color}") + + return True + + def _scan_video_devices(self): + """ + Scan and log available video input devices. + Returns: + Default device index for the current mode. + """ + logger.info("=== Available Video Devices ===") + + available_devices = [] + + # Test device indices 0-1 (covers built-in webcam + external camera) + for device_index in range(2): + try: + cap = cv2.VideoCapture(device_index) + if cap.isOpened(): + + # Get device properties + width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + + device_info = { + 'index': device_index, + 'width': width, + 'height': height, + 'fps': fps, + } + available_devices.append(device_info) + + logger.info(f"Device {device_index}: {width}x{height} @ {fps:.1f}fps") + + cap.release() + except Exception as e: + logger.error(f"Error accessing device {device_index}: {e}") + + if not available_devices: + logger.warning("No video devices found") + return -1 + else: + logger.info(f"Found {len(available_devices)} input device(s)") + logger.info(f"Default Input Device: 0") + + return 0 + + def _enableStream(self): + """ + Enable the video stream for input (camera/file) or output (file/display). + + Initializes the OpenCV VideoCapture or VideoWriter as needed. + Handles both new and existing files, and sets up frame dropping if input FPS > requested FPS. + Returns: + None + """ + + if self.mode != MODE_VIDEO_INPUT and self.mode != MODE_VIDEO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.frame_ratio = 0 + self.frame_drop = 0 + + if self.stream is not None: + self.stream.release() + self.stream = None + + if self.filename == None: + self.video = True + + if self.video: + if self.mode == MODE_VIDEO_INPUT: + # Input mode: read from camera or video file + if self.filename == None: + # No filename specified: use camera interface + logger.debug("_enableStream: use camera interface for input streaming") + self.stream = cv2.VideoCapture(self.device) + + if not self.stream.isOpened(): + logger.error("_enableStream: failed to open Camera interface") + return + else: + # Filename specified: use video file + logger.debug("_enableStream: use file interface for input streaming") + self.stream = cv2.VideoCapture(self.filename) + + # Display stream properties + logger.info(f"_enableStream: source stream properties: width={self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)}, height={self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)}, fps={self.stream.get(cv2.CAP_PROP_FPS)}") + + # Get the video stream FPS + video_fps = self.stream.get(cv2.CAP_PROP_FPS) + + if video_fps > self.frame_rate: + self.frame_ratio = video_fps / self.frame_rate + logger.debug(f"_enableStream: source/target frame ratio={self.frame_ratio}") + + elif self.mode == MODE_VIDEO_OUTPUT: + # Output mode: write to video file or display window + if self.filename != None: + # Filename specified: output to file + logger.debug("_enableStream: output stream to a file") + + extension = self.filename.suffix.lstrip('.').lower() + fourcc = cv2.VideoWriter_fourcc(*f'{video_fourcc[extension]}') + + self.stream = cv2.VideoWriter(self.filename, fourcc, self.frame_rate, (self.frame_width, self.frame_height)) + else: + logger.debug("_enableStream: output stream to display window") + + self.active = True + logger.info("_enableStream: stream enabled") + + def _disableStream(self): + """ + Disable the video stream and release OpenCV resources. + + For input streams, saves the current frame index for resuming later. + Returns: + None + """ + self.active = False + if self.stream is not None: + # Clean-up stream resources and invalidate object + self.stream.release() + self.stream = None + + logger.info("_disableStream: stream disabled") + + def __cropFrame(self, frame, target_aspect_ratio): + """ + Crop the input frame to match the specified aspect ratio. + + Args: + frame: The input frame (as NumPy array) to be cropped. + aspect_ratio: The target aspect ratio (width/height). + Returns: + frame: The cropped frame. + """ + logger.debug(f"__cropFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_aspect_ratio={target_aspect_ratio}") + + # NumPY array shape is (height, width, channels) + frame_h = frame.shape[0] + frame_w = frame.shape[1] + + frame_aspect_ratio = frame_w / frame_h + + if frame_aspect_ratio > target_aspect_ratio: + # Frame is wider than target -> crop left and right + new_w = int(frame_h * target_aspect_ratio) + left = (frame_w - new_w) // 2 + right = left + new_w + cropped = frame[:, left:right] + else: + # Frame is taller than target -> crop top and bottom + new_h = int(frame_w / target_aspect_ratio) + top = (frame_h - new_h) // 2 + bottom = top + new_h + cropped = frame[top:bottom, :] + + logger.debug(f"__cropFrame: cropped_size=({cropped.shape[1]}, {cropped.shape[0]})") + + return cropped + + def __resizeFrame(self, frame, target_width, target_height): + """ + Resize the input frame to the target width and height. + + Args: + frame: The input frame (as NumPy array) to be resized. + target_width: The target width in pixels. + target_height: The target height in pixels. + Returns: + frame: The resized frame. + """ + logger.debug(f"__resizeFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_size=({target_width}, {target_height})") + + try: + frame = cv2.resize(frame, (target_width, target_height)) + except Exception as e: + logger.error(f"Error in resizeFrame(): {e}") + + logger.debug(f"__resizeFrame: resized_size=({frame.shape[1]}, {frame.shape[0]})") + + return frame + + def __convertToBGR(self, frame): + """ + Convert the input frame to BGR color space if needed. + + Args: + frame: The input frame (as NumPy array) to be converted. + Returns: + frame: The converted frame in BGR color space. + """ + if self.frame_color == self.RGB888: + # Convert RGB to BGR + logger.debug(f"__convertToBGR: converting frame from RGB to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) + elif self.frame_color == self.GRAYSCALE8: + # Convert Grayscale to BGR + logger.debug(f"__convertToBGR: converting frame from Grayscale to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) + elif self.frame_color == self.BGR565: + # Convert BGR565 to BGR + logger.debug(f"__convertToBGR: converting frame from BGR565 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR5652BGR) + elif self.frame_color == self.YUV420: + # Convert YUV420 to BGR + logger.debug(f"__convertToBGR: converting frame from YUV420 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_I420) + elif self.frame_color == self.NV12: + # Convert NV12 to BGR + logger.debug(f"__convertToBGR: converting frame from NV12 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV12) + elif self.frame_color == self.NV21: + # Convert NV21 to BGR + logger.debug(f"__convertToBGR: converting frame from NV21 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV21) + + return frame + + def __convertFromBGR(self, frame): + """ + Convert the input BGR frame to the specified color space if needed. + + Args: + frame: The input frame (as NumPy array in BGR color space) to be converted. + Returns: + frame: The converted frame in the specified color space. + """ + if self.frame_color == self.RGB888: + # Convert BGR to RGB + logger.debug(f"__convertFromBGR: converting frame from BGR to RGB") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + elif self.frame_color == self.GRAYSCALE8: + # Convert BGR to Grayscale + logger.debug(f"__convertFromBGR: converting frame from BGR to Grayscale") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + elif self.frame_color == self.BGR565: + # Convert BGR to BGR565 + logger.debug(f"__convertFromBGR: converting frame from BGR to BGR565") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGR565) + elif self.frame_color == self.YUV420: + # Convert BGR to YUV420 + logger.debug(f"__convertFromBGR: converting frame from BGR to YUV420") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420) + elif self.frame_color == self.NV12: + # Convert BGR to NV12 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV12") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV12) + elif self.frame_color == self.NV21: + # Convert BGR to NV21 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV21") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV21) + + return frame + + # Read frame from source + def _readFrame(self): + """Read a single frame from the current video or image source. + + If the stream is not active or end-of-stream is reached, returns an empty bytearray. + For video sources, handles frame dropping to match requested frame rate. + For image sources, reads the image once and sets end-of-stream. + Resizes and converts color space as needed. + Returns: + frame: The read frame as a bytearray, or empty if no frame is available. + """ + frame = bytearray() + + # If the stream is not active, return empty frame + if not self.active: + logger.error("_readFrame: stream not active") + return frame + + # If end-of-stream has been reached, return empty frame + if self.eos: + logger.debug("_readFrame: end of stream reached") + return frame + + if self.video: + # Video source, read frame from the video stream + _, frame_in = self.stream.read() # Frame is numpy.ndarray, (height, width, channels), dtype=uint8 + + if frame_in is not None: + logger.debug(f"_readFrame: frame captured, size=({frame_in.shape[1]}, {frame_in.shape[0]})") + + # Handle frame dropping if input FPS > requested FPS + if self.frame_ratio > 1: + # Accumulate fractional frames to drop + self.frame_drop += (self.frame_ratio - 1) + + if self.frame_drop > 1: + logger.debug(f"_readFrame: frames to drop={self.frame_drop}") + drop = int(self.frame_drop // 1) + + # Drop the required number of frames to match requested FPS + for i in range(drop): + _, _ = self.stream.read() + logger.debug(f"_readFrame: frames dropped={drop}") + self.frame_drop -= drop + logger.debug(f"_readFrame: frames left to drop={self.frame_drop}") + else: + # Frame not read, mark end-of-stream + self.eos = True + logger.debug("_readFrame: end of stream.") + else: + # For image sources, read the image once and set end-of-stream + frame_in = cv2.imread(self.filename) + self.eos = True + logger.debug("_readFrame: end of stream.") + + if frame_in is not None: + target_width = self.frame_width + target_height = self.frame_height + + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size aspect ratio + target_aspect_ratio = target_width / target_height + frame_aspect_ratio = frame_in_width / frame_in_height + + if not np.isclose(frame_aspect_ratio, target_aspect_ratio, rtol=1e-3): + logger.debug(f"_readFrame: frame aspect ratio {frame_aspect_ratio:.2f} does not match target {target_aspect_ratio:.2f}, cropping frame") + frame_in = self.__cropFrame(frame_in, target_aspect_ratio) + + # Update frame size after cropping + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size + if (frame_in_width != target_width) or (frame_in_height != target_height): + logger.debug(f"_readFrame: frame size ({frame_in_width}, {frame_in_height}) does not match target ({target_width}, {target_height}), resizing frame") + frame_in = self.__resizeFrame(frame_in, target_width, target_height) + + # Convert frame color space to target color space + frame_in = self.__convertFromBGR(frame_in) + + # Convert the frame to a bytearray for transmission + frame = bytearray(frame_in.tobytes()) + + return frame + + def _writeFrame(self, frame): + """ + Write a frame to the output destination (file or display window). + + If filename is empty, displays the frame in a window. + If filename is set and video mode, writes frame to video file. + If filename is set and image mode, saves frame as image file. + Args: + frame: The input frame as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeFrame: frame size={len(frame)} bytes") + + # If the stream is not active, do nothing + if not self.active: + logger.error("_writeFrame: stream not active") + return + + try: + # Decode the frame from bytearray to a NumPy array + decoded_frame = np.frombuffer(frame, dtype=np.uint8) + + # Reshape the decoded frame to match the target resolution + decoded_frame = decoded_frame.reshape((self.frame_height, self.frame_width, 3)) + logger.debug(f"_writeFrame: decoded frame size=({decoded_frame.shape[1]}, {decoded_frame.shape[0]})") + + # Convert color space to BGR + frame_out = self.__convertToBGR(decoded_frame) + + if self.filename == None: + logger.debug("_writeFrame: display frame in window") + # If no filename, display the frame in a window + cv2.imshow(self.filename, frame_out) + cv2.waitKey(10) + else: + if self.video: + logger.debug("_writeFrame: write frame to video file") + # Write frame to video file + self.stream.write(np.uint8(frame_out)) + else: + logger.debug("_writeFrame: write frame as image file") + # Write frame as image file + cv2.imwrite(self.filename, frame_out) + + except Exception as e: + # Output exception debug information but continue + logger.error(f"Exception in _writeFrame: {type(e).__name__}: {e}", exc_info=True) + pass + + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write frames, close server. + Sends responses or frame data as appropriate. + """ + logger.info("Video server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2], payload[3]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.FRAME_READ: + frame = self._readFrame() + conn.send_bytes(frame) + conn.send(self.eos) + + elif cmd == self.FRAME_WRITE: + frame = conn.recv_bytes() + self._writeFrame(frame) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + + def stop(self): + """ + Stop the video server. + + Releases all resources and closes any open windows. + Returns: + None + """ + self._disableStream() + if (self.mode == MODE_VIDEO_OUTPUT) and (self.filename == None): + try: + cv2.destroyAllWindows() + except Exception: + pass + self.listener.close() + logger.info("Video server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the video server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Video Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = VideoServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-315/Board-U65.clayer.yml b/board/Corstone-315/Board-U65.clayer.yml new file mode 100644 index 0000000..b63ea8d --- /dev/null +++ b/board/Corstone-315/Board-U65.clayer.yml @@ -0,0 +1,64 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U65 + for-board: ARM::SSE-315 + for-device: ARM::SSE-315-FVP + + connections: + - connect: Corstone-315 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-315.h\" + - ETHOSU65 + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::SSE_315_BSP@1.0.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U55 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-315.h diff --git a/board/Corstone-315/Board.clayer.yml b/board/Corstone-315/Board.clayer.yml new file mode 100644 index 0000000..dc397ff --- /dev/null +++ b/board/Corstone-315/Board.clayer.yml @@ -0,0 +1,59 @@ +layer: + type: Board + description: Board setup for AI/ML + for-board: ARM::SSE-315 + for-device: ARM::SSE-315-FVP + + connections: + - connect: Corstone-315 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-315.h\" + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::AVH_FVP + - pack: ARM::SSE_315_BSP@1.0.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-315.h diff --git a/board/Corstone-315/Corstone-315.h b/board/Corstone-315/Corstone-315.h new file mode 100644 index 0000000..50b23c5 --- /dev/null +++ b/board/Corstone-315/Corstone-315.h @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef CORSTONE_315_H_ +#define CORSTONE_315_H_ + +#include "Driver_USART.h" +#include "cmsis_vstream.h" + +// CMSIS Driver instances of Board peripherals +#define CMSIS_DRIVER_USART 0 // CMSIS Driver USART instance number + +// Retarget stdio to CMSIS UART +#define RETARGET_STDIO_UART 0 + +// CMSIS Drivers +extern ARM_DRIVER_USART Driver_USART0; /* Serial */ +extern vStreamDriver_t Driver_vStreamAudioIn; /* Audio In Stream */ +extern vStreamDriver_t Driver_vStreamAudioOut; /* Audio Out Stream */ +extern vStreamDriver_t Driver_vStreamVideoIn; /* Video In Stream */ +extern vStreamDriver_t Driver_vStreamVideoOut; /* Video Out Stream */ + +#ifdef CMSIS_shield_header +#include CMSIS_shield_header +#endif + +#endif /* CORSTONE_315_H_ */ diff --git a/board/Corstone-315/README.md b/board/Corstone-315/README.md new file mode 100644 index 0000000..1b612dd --- /dev/null +++ b/board/Corstone-315/README.md @@ -0,0 +1,35 @@ +# Board: Arm SSE-315 + +## Board Layer for Corstone-315 FVP + +Device: SSE-315-FVP + +### System Configuration + +| System Component | Setting +|:------------------------|:---------------------------------- +| Heap | 768 kB (configured in linker file) +| Stack (MSP) | 32 kB (configured in linker file) + +### STDIO mapping + +**STDIO** is routed to terminal via **UART0** peripheral + +### CMSIS-Driver mapping + +| CMSIS-Driver | Peripheral | Connection +|:-----------------------|:-----------|:---------------------- +| Driver_USART0 | UART0 | STDOUT, STDERR +| Driver_vStreamAudioIn | VSI0 | CMSIS_VSTREAM_AUDIO_IN +| Driver_vStreamAudioOut | VSI1 | CMSIS_VSTREAM_AUDIO_OUT +| Driver_vStreamVideoIn | VSI4 | CMSIS_VSTREAM_VIDEO_IN +| Driver_vStreamVideoOut | VSI6 | CMSIS_VSTREAM_VIDEO_OUT + +### CMSIS-Driver vStream configuration + +| Driver | Stream Format Description +|:-----------------------|:---------------------------------------------------- +| 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) diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h new file mode 100644 index 0000000..fd1d7d0 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 new file mode 100644 index 0000000..a4e79fe --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h new file mode 100644 index 0000000..da9aa7e --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 new file mode 100644 index 0000000..b59bf69 --- /dev/null +++ b/board/Corstone-315/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src b/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src new file mode 100644 index 0000000..233a6de --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/ac6_linker_script.sct.src @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE 8 +#else +#define __STACKSEAL_SIZE 0 +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + + ER_ROM0 __ROM0_BASE __ROM0_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + } + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) { + *(Veneer$$CMSE) + } +#endif +} + +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + + ER_ROM1 __ROM1_BASE __ROM1_SIZE { + *(+RO +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) { + *.o(.bss.noinit) + *.o(.bss.noinit.*) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#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) + + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + ; NN Model Binary Representation + *.o (nn_model) + + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h b/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h new file mode 100644 index 0000000..008ff9a --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif +#ifdef RTE_I2C1 +#define I2C1_SBCON_S +#define I2C1_SBCON_DEV I2C1_SBCON_DEV_S +#endif +#ifdef RTE_I2C2 +#define I2C2_SBCON_S +#define I2C2_SBCON_DEV I2C2_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif +#ifdef RTE_USART2 +#define UART2_CMSDK_S +#define UART2_CMSDK_DEV UART2_CMSDK_DEV_S +#endif +#ifdef RTE_USART3 +#define UART3_CMSDK_S +#define UART3_CMSDK_DEV UART3_CMSDK_DEV_S +#endif +#ifdef RTE_USART4 +#define UART4_CMSDK_S +#define UART4_CMSDK_DEV UART4_CMSDK_DEV_S +#endif +#ifdef RTE_USART5 +#define UART5_CMSDK_S +#define UART5_CMSDK_DEV UART5_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 315 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN0_S +#define PPC_CORSTONE315_MAIN0_DEV PPC_CORSTONE315_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP0_S +#define PPC_CORSTONE315_MAIN_EXP0_DEV PPC_CORSTONE315_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP1_S +#define PPC_CORSTONE315_MAIN_EXP1_DEV PPC_CORSTONE315_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP2_S +#define PPC_CORSTONE315_MAIN_EXP2_DEV PPC_CORSTONE315_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP3_S +#define PPC_CORSTONE315_MAIN_EXP3_DEV PPC_CORSTONE315_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH0_S +#define PPC_CORSTONE315_PERIPH0_DEV PPC_CORSTONE315_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH1_S +#define PPC_CORSTONE315_PERIPH1_DEV PPC_CORSTONE315_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP0_S +#define PPC_CORSTONE315_PERIPH_EXP0_DEV PPC_CORSTONE315_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP1_S +#define PPC_CORSTONE315_PERIPH_EXP1_DEV PPC_CORSTONE315_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP2_S +#define PPC_CORSTONE315_PERIPH_EXP2_DEV PPC_CORSTONE315_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP3_S +#define PPC_CORSTONE315_PERIPH_EXP3_DEV PPC_CORSTONE315_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* Key Management Unit */ +#ifdef RTE_KMU +#define KMU_S +#define KMU_DEV KMU_DEV_S +#endif + +/* Lifecycle Manager */ +#ifdef RTE_LCM +#define LCM_S +#define LCM_DEV LCM_DEV_S +#endif + +/* Security Alarm Manager */ +#ifdef RTE_SAM +#define SAM_S +#define SAM_DEV SAM_DEV_S +#endif + +/* HDLCD Video */ +#ifdef RTE_HDLCD +#define HDLCD_NS +#define HDLCD_DEV HDLCD_DEV_NS +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI0 +#define SPI0_PL022_S +#define SPI0_PL022_DEV SPI0_PL022_DEV_S +#endif +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif +#ifdef RTE_SPI2 +#define SPI2_PL022_S +#define SPI2_PL022_DEV SPI2_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h.base@1.1.0 b/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h.base@1.1.0 new file mode 100644 index 0000000..008ff9a --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/device_cfg.h.base@1.1.0 @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif +#ifdef RTE_I2C1 +#define I2C1_SBCON_S +#define I2C1_SBCON_DEV I2C1_SBCON_DEV_S +#endif +#ifdef RTE_I2C2 +#define I2C2_SBCON_S +#define I2C2_SBCON_DEV I2C2_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif +#ifdef RTE_USART2 +#define UART2_CMSDK_S +#define UART2_CMSDK_DEV UART2_CMSDK_DEV_S +#endif +#ifdef RTE_USART3 +#define UART3_CMSDK_S +#define UART3_CMSDK_DEV UART3_CMSDK_DEV_S +#endif +#ifdef RTE_USART4 +#define UART4_CMSDK_S +#define UART4_CMSDK_DEV UART4_CMSDK_DEV_S +#endif +#ifdef RTE_USART5 +#define UART5_CMSDK_S +#define UART5_CMSDK_DEV UART5_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 315 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN0_S +#define PPC_CORSTONE315_MAIN0_DEV PPC_CORSTONE315_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP0_S +#define PPC_CORSTONE315_MAIN_EXP0_DEV PPC_CORSTONE315_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP1_S +#define PPC_CORSTONE315_MAIN_EXP1_DEV PPC_CORSTONE315_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP2_S +#define PPC_CORSTONE315_MAIN_EXP2_DEV PPC_CORSTONE315_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE315 +#define PPC_CORSTONE315_MAIN_EXP3_S +#define PPC_CORSTONE315_MAIN_EXP3_DEV PPC_CORSTONE315_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH0_S +#define PPC_CORSTONE315_PERIPH0_DEV PPC_CORSTONE315_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH1_S +#define PPC_CORSTONE315_PERIPH1_DEV PPC_CORSTONE315_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP0_S +#define PPC_CORSTONE315_PERIPH_EXP0_DEV PPC_CORSTONE315_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP1_S +#define PPC_CORSTONE315_PERIPH_EXP1_DEV PPC_CORSTONE315_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP2_S +#define PPC_CORSTONE315_PERIPH_EXP2_DEV PPC_CORSTONE315_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE315 +#define PPC_CORSTONE315_PERIPH_EXP3_S +#define PPC_CORSTONE315_PERIPH_EXP3_DEV PPC_CORSTONE315_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* Key Management Unit */ +#ifdef RTE_KMU +#define KMU_S +#define KMU_DEV KMU_DEV_S +#endif + +/* Lifecycle Manager */ +#ifdef RTE_LCM +#define LCM_S +#define LCM_DEV LCM_DEV_S +#endif + +/* Security Alarm Manager */ +#ifdef RTE_SAM +#define SAM_S +#define SAM_DEV SAM_DEV_S +#endif + +/* HDLCD Video */ +#ifdef RTE_HDLCD +#define HDLCD_NS +#define HDLCD_DEV HDLCD_DEV_NS +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI0 +#define SPI0_PL022_S +#define SPI0_PL022_DEV SPI0_PL022_DEV_S +#endif +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif +#ifdef RTE_SPI2 +#define SPI2_PL022_S +#define SPI2_PL022_DEV SPI2_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src b/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src new file mode 100644 index 0000000..2e2ef6f --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/gcc_linker_script.ld.src @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + 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) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __noinit_start + * __noinit_end + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .boot : + { + KEEP(*(.vectors)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .text : + { + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM1 + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM1 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM1 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + LONG (LOADADDR(.init_buf)) + LONG (ADDR(.init_buf)) + LONG (SIZEOF(.init_buf) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM1 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM1 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM1 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM1 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit (NOLOAD) : + { + . = ALIGN(4); + __noinit_start = .; + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + __noinit_end = .; + } > RAM0 + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + /* Non-initialized buffers in fast access RAM */ + .cache (NOLOAD): + { + . = ALIGN(32); + *(*ethos_cache_buf) /* Ethos-U Cache Area */ + *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + } > RAM1 + + /* Initialized buffers in fast access RAM */ + /* Entry must exist in .copy.table */ + .init_buf : + { + /* Add objects that go into RAM1 */ + } > RAM1 AT > ROM1 + + .rom2 : + { + *(*nn_model) /* NN Model Binary Representation */ + } > ROM2 + + .rom3 : + { + /* Add objects that go into ROM3 */ + } > ROM3 +} diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src b/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src new file mode 100644 index 0000000..ea02d53 --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/iar_linker_script.icf.src @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define memory mem with size = 4G; + +#if __ROM0_SIZE > 0 + define region ROM0_region = mem:[from __ROM0_BASE to (__ROM0_BASE+__ROM0_SIZE-1)]; +#else + define region ROM0_region = []; +#endif + +#if __ROM1_SIZE > 0 + define region ROM1_region = mem:[from __ROM1_BASE to (__ROM1_BASE+__ROM1_SIZE-1)]; +#else + define region ROM1_region = []; +#endif + +#if __ROM2_SIZE > 0 + define region ROM2_region = mem:[from __ROM2_BASE to (__ROM2_BASE+__ROM2_SIZE-1)]; +#else + define region ROM2_region = []; +#endif + +#if __ROM3_SIZE > 0 + define region ROM3_region = mem:[from __ROM3_BASE to (__ROM3_BASE+__ROM3_SIZE-1)]; +#else + 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 + define region RAM0_region = []; +#endif + +#if __RAM1_SIZE > 0 + define region RAM1_region = mem:[from __RAM1_BASE to (__RAM1_BASE+__RAM1_SIZE-1)]; +#else + define region RAM1_region = []; +#endif + +#if __RAM2_SIZE > 0 + define region RAM2_region = mem:[from __RAM2_BASE to (__RAM2_BASE+__RAM2_SIZE-1)]; +#else + define region RAM2_region = []; +#endif + +#if __RAM3_SIZE > 0 + define region RAM3_region = mem:[from __RAM3_BASE to (__RAM3_BASE+__RAM3_SIZE-1)]; +#else + 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)) +{ + // Required in a multi-threaded application + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +place at address mem:__ROM0_BASE { readonly section .intvec }; + +if (!isempty(ROM_region)) +{ + place in ROM_region { readonly }; +} + +if (!isempty(RAM_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 }; +} diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c b/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c new file mode 100644 index 0000000..335f91f --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE315.h" +#include "system_SSE315.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(SDC_Handler) +DEFAULT_IRQ_HANDLER(KMU_Handler) +DEFAULT_IRQ_HANDLER(DMA_SEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_NONSEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_SECURITY_VIOLATION_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) +DEFAULT_IRQ_HANDLER(SAM_Critical_Severity_Fault_Handler) +DEFAULT_IRQ_HANDLER(SAM_Severity_Fault_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(RTC_Handler) +DEFAULT_IRQ_HANDLER(ISP_C55_Handler) +DEFAULT_IRQ_HANDLER(HDLCD_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + SDC_Handler, /* 15: Secure Debug Channel Handler */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + KMU_Handler, /* 20: KMU Handler */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + DMA_SEC_Combined_Handler, /* 24: DMA Secure Combined Handler */ + DMA_NONSEC_Combined_Handler, /* 25: DMA Non-Secure Combined Handler */ + DMA_SECURITY_VIOLATION_Handler, /* 26: DMA Security Violation Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + SAM_Critical_Severity_Fault_Handler, /* 30: SAM Critical Severity Fault Handler */ + SAM_Severity_Fault_Handler, /* 31: SAM Severity Fault Handler */ + + /* External interrupts */ + 0, /* 32: Reserved */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + 0, /* 51: Reserved */ + 0, /* 52: Reserved */ + 0, /* 53: Reserved */ + 0, /* 54: Reserved */ + 0, /* 55: Reserved */ + 0, /* 56: Reserved */ + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + 0, /* 73: Reserved */ + 0, /* 74: Reserved */ + 0, /* 75: Reserved */ + 0, /* 76: Reserved */ + 0, /* 77: Reserved */ + 0, /* 78: Reserved */ + 0, /* 79: Reserved */ + 0, /* 80: Reserved */ + 0, /* 81: Reserved */ + 0, /* 82: Reserved */ + 0, /* 83: Reserved */ + 0, /* 84: Reserved */ + 0, /* 85: Reserved */ + 0, /* 86: Reserved */ + 0, /* 87: Reserved */ + 0, /* 88: Reserved */ + 0, /* 89: Reserved */ + 0, /* 90: Reserved */ + 0, /* 91: Reserved */ + 0, /* 92: Reserved */ + 0, /* 93: Reserved */ + 0, /* 94: Reserved */ + 0, /* 95: Reserved */ + 0, /* 96: Reserved */ + 0, /* 97: Reserved */ + 0, /* 98: Reserved */ + 0, /* 99: Reserved */ + 0, /* 100: Reserved */ + 0, /* 101: Reserved */ + 0, /* 102: Reserved */ + 0, /* 103: Reserved */ + 0, /* 104: Reserved */ + 0, /* 105: Reserved */ + 0, /* 106: Reserved */ + 0, /* 107: Reserved */ + 0, /* 108: Reserved */ + 0, /* 109: Reserved */ + 0, /* 110: Reserved */ + 0, /* 111: Reserved */ + 0, /* 112: Reserved */ + 0, /* 113: Reserved */ + 0, /* 114: Reserved */ + 0, /* 115: Reserved */ + 0, /* 116: Reserved */ + 0, /* 117: Reserved */ + 0, /* 118: Reserved */ + 0, /* 119: Reserved */ + 0, /* 120: Reserved */ + 0, /* 121: Reserved */ + 0, /* 122: Reserved */ + 0, /* 123: Reserved */ + 0, /* 124: Reserved */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + 0, /* 127: Reserved */ + RTC_Handler, /* 128: UART 5 combined Interrupt */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + ISP_C55_Handler, /* 132: ISP C55 Handler */ + HDLCD_Handler, /* 133: HDLCD Handler */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c.base@1.1.0 b/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c.base@1.1.0 new file mode 100644 index 0000000..335f91f --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/startup_SSE315.c.base@1.1.0 @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE315.h" +#include "system_SSE315.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +void __NO_RETURN Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +void __NO_RETURN __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(SDC_Handler) +DEFAULT_IRQ_HANDLER(KMU_Handler) +DEFAULT_IRQ_HANDLER(DMA_SEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_NONSEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_SECURITY_VIOLATION_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) +DEFAULT_IRQ_HANDLER(SAM_Critical_Severity_Fault_Handler) +DEFAULT_IRQ_HANDLER(SAM_Severity_Fault_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(RTC_Handler) +DEFAULT_IRQ_HANDLER(ISP_C55_Handler) +DEFAULT_IRQ_HANDLER(HDLCD_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + SDC_Handler, /* 15: Secure Debug Channel Handler */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + KMU_Handler, /* 20: KMU Handler */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + DMA_SEC_Combined_Handler, /* 24: DMA Secure Combined Handler */ + DMA_NONSEC_Combined_Handler, /* 25: DMA Non-Secure Combined Handler */ + DMA_SECURITY_VIOLATION_Handler, /* 26: DMA Security Violation Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + SAM_Critical_Severity_Fault_Handler, /* 30: SAM Critical Severity Fault Handler */ + SAM_Severity_Fault_Handler, /* 31: SAM Severity Fault Handler */ + + /* External interrupts */ + 0, /* 32: Reserved */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + 0, /* 51: Reserved */ + 0, /* 52: Reserved */ + 0, /* 53: Reserved */ + 0, /* 54: Reserved */ + 0, /* 55: Reserved */ + 0, /* 56: Reserved */ + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + 0, /* 73: Reserved */ + 0, /* 74: Reserved */ + 0, /* 75: Reserved */ + 0, /* 76: Reserved */ + 0, /* 77: Reserved */ + 0, /* 78: Reserved */ + 0, /* 79: Reserved */ + 0, /* 80: Reserved */ + 0, /* 81: Reserved */ + 0, /* 82: Reserved */ + 0, /* 83: Reserved */ + 0, /* 84: Reserved */ + 0, /* 85: Reserved */ + 0, /* 86: Reserved */ + 0, /* 87: Reserved */ + 0, /* 88: Reserved */ + 0, /* 89: Reserved */ + 0, /* 90: Reserved */ + 0, /* 91: Reserved */ + 0, /* 92: Reserved */ + 0, /* 93: Reserved */ + 0, /* 94: Reserved */ + 0, /* 95: Reserved */ + 0, /* 96: Reserved */ + 0, /* 97: Reserved */ + 0, /* 98: Reserved */ + 0, /* 99: Reserved */ + 0, /* 100: Reserved */ + 0, /* 101: Reserved */ + 0, /* 102: Reserved */ + 0, /* 103: Reserved */ + 0, /* 104: Reserved */ + 0, /* 105: Reserved */ + 0, /* 106: Reserved */ + 0, /* 107: Reserved */ + 0, /* 108: Reserved */ + 0, /* 109: Reserved */ + 0, /* 110: Reserved */ + 0, /* 111: Reserved */ + 0, /* 112: Reserved */ + 0, /* 113: Reserved */ + 0, /* 114: Reserved */ + 0, /* 115: Reserved */ + 0, /* 116: Reserved */ + 0, /* 117: Reserved */ + 0, /* 118: Reserved */ + 0, /* 119: Reserved */ + 0, /* 120: Reserved */ + 0, /* 121: Reserved */ + 0, /* 122: Reserved */ + 0, /* 123: Reserved */ + 0, /* 124: Reserved */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + 0, /* 127: Reserved */ + RTC_Handler, /* 128: UART 5 combined Interrupt */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + ISP_C55_Handler, /* 132: ISP C55 Handler */ + HDLCD_Handler, /* 133: HDLCD Handler */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c b/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c new file mode 100644 index 0000000..81d74c3 --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE315.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c.base@1.1.0 b/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c.base@1.1.0 new file mode 100644 index 0000000..81d74c3 --- /dev/null +++ b/board/Corstone-315/RTE/Device/SSE-315-FVP/system_SSE315.c.base@1.1.0 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE315.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-315/ethos_setup.c b/board/Corstone-315/ethos_setup.c new file mode 100644 index 0000000..ca26dfa --- /dev/null +++ b/board/Corstone-315/ethos_setup.c @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + + #include + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "ethosu_driver.h" +#include "main.h" + +#if defined(ETHOSU65) || defined(ETHOSU85) +/* Define Ethos-U NPU cache buffer size */ +#ifndef ETHOS_CACHE_BUF_SIZE +#define ETHOS_CACHE_BUF_SIZE 393216 +#endif + +/* Define Ethos-U cache buffer alignment */ +#ifndef ETHOS_CACHE_BUF_ALIGNMENT +#define ETHOS_CACHE_BUF_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))) +#endif +#endif + +/* Define Ethos-U NPU security mode */ +#ifndef ETHOS_SECURE_ENABLE +#define ETHOS_SECURE_ENABLE 1 +#endif + +/* Define Ethos-U NPU privilege mode */ +#ifndef ETHOS_PRIVILEGE_ENABLE +#define ETHOS_PRIVILEGE_ENABLE 1 +#endif + +/* 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; +#endif + +/* + Ethos NPU interrupt handler. +*/ +void NPU0_Handler(void) { + ethosu_irq_handler(&EthosDriver); +} + +/* + Initialize the Ethos NPU driver. +*/ +void ethos_setup (void) { + void * const ethos_base_addr = (void *)NPU0_APB_BASE_S; + struct ethosu_hw_info hw_info; + int rval; + + /* 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 */ + #else + 0, /* Cache memory pointer */ + 0, /* Cache memory size */ + #endif + ETHOS_SECURE_ENABLE, /* Secure enable */ + ETHOS_PRIVILEGE_ENABLE); /* Privileged mode */ + if (rval != 0) { + printf("Failed to initialize Arm Ethos-U driver\n"); + } + else { + NVIC_EnableIRQ(NPU0_IRQn); + + ethosu_get_hw_info(&EthosDriver, &hw_info); + + printf("Ethos-U version info:\n"); + printf("\tArch: v%u.%u.%u\n", hw_info.version.arch_major_rev, + hw_info.version.arch_minor_rev, + hw_info.version.arch_patch_rev); + printf("\tMACs/cc: %u\n", (uint32_t)(1 << hw_info.cfg.macs_per_cc)); + printf("\tCmd stream: v%u\n", hw_info.cfg.cmd_stream_version); + } +} diff --git a/board/Corstone-315/fvp_config.txt b/board/Corstone-315/fvp_config.txt new file mode 100644 index 0000000..225e1be --- /dev/null +++ b/board/Corstone-315/fvp_config.txt @@ -0,0 +1,8 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.num_macs=256 # (int , init-time) default = '0x100' : Number of 8x8 MACs performed per cycle (256 or 512). : [0x100:0x200] +mps4_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) +mps4_board.visualisation.disable-visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +vis_hdlcd.disable_visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +#------------------------------------------------------------------------------ diff --git a/board/Corstone-315/main.c b/board/Corstone-315/main.c new file mode 100644 index 0000000..69b3485 --- /dev/null +++ b/board/Corstone-315/main.c @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "main.h" + +int main (void) { + + /* Initialize STDIO */ + stdio_init(); + + #if defined(ETHOSU_ARCH) + /* Initialize Ethos NPU */ + ethos_setup(); + #endif + + return (app_main()); +} diff --git a/board/Corstone-315/main.h b/board/Corstone-315/main.h new file mode 100644 index 0000000..6e2048e --- /dev/null +++ b/board/Corstone-315/main.h @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2020-2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef MAIN_H__ +#define MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototypes */ +extern int app_main (void); +extern int stdio_init (void); + +#if defined(ETHOSU_ARCH) +extern void ethos_setup (void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/Corstone-315/regions_SSE-315.h b/board/Corstone-315/regions_SSE-315.h new file mode 100644 index 0000000..fba4be3 --- /dev/null +++ b/board/Corstone-315/regions_SSE-315.h @@ -0,0 +1,115 @@ +#ifndef REGIONS_SSE_315_H +#define REGIONS_SSE_315_H + +#include "sse315_memmap_s.h" +#include "sse315_memmap_ns.h" + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// ROM Configuration +// ======================= +// __ROM0 +// Base address +// Defines base address of memory region. +// Contains Startup and Vector Table +// Default: BOOT_ROM_S_BASE +#define __ROM0_BASE BOOT_ROM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: BOOT_ROM_S_SIZE +#define __ROM0_SIZE BOOT_ROM_S_SIZE +// + +// __ROM1 +// Base address +// Defines base address of memory region. +// Default: FPGA_SRAM_S_BASE +#define __ROM1_BASE FPGA_SRAM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: FPGA_SRAM_S_SIZE +#define __ROM1_SIZE FPGA_SRAM_S_SIZE +// + +// __ROM2 +// Base address +// Defines base address of memory region. +// Default: DDR4_3_S_BASE +#define __ROM2_BASE DDR4_3_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_3_S_SIZE +#define __ROM2_SIZE DDR4_3_S_SIZE +// + +// __ROM3 +// Base address +// Defines base address of memory region. +// Default: QSPI_FLASH_S_BASE +#define __ROM3_BASE QSPI_FLASH_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: QSPI_FLASH_S_SIZE +#define __ROM3_SIZE QSPI_FLASH_S_SIZE +// + +// + +// RAM Configuration +// ======================= +// __RAM0 +// Base address +// Defines base address of memory region. +// Default: DDR4_1_S_BASE +#define __RAM0_BASE DDR4_1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_1_S_SIZE +#define __RAM0_SIZE DDR4_1_S_SIZE +// + +// __RAM1 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM0_S_BASE +#define __RAM1_BASE SRAM_VM0_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM0_S_SIZE +#define __RAM1_SIZE SRAM_VM0_S_SIZE +// + +// __RAM2 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM1_S_BASE +#define __RAM2_BASE SRAM_VM1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM1_S_SIZE +#define __RAM2_SIZE SRAM_VM1_S_SIZE +// + +// __RAM3 +// Base address +// Defines base address of memory region. +// Default: DTCM_S_BASE +#define __RAM3_BASE DTCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DTCM_S_SIZE +#define __RAM3_SIZE DTCM_S_SIZE +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00001000 +#define __HEAP_SIZE 0x00018000 +// + +#endif /* REGIONS_SSE_315_H */ diff --git a/board/Corstone-315/retarget_stdio.c b/board/Corstone-315/retarget_stdio.c new file mode 100644 index 0000000..f553eed --- /dev/null +++ b/board/Corstone-315/retarget_stdio.c @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Name: retarget_stdio.c + * Purpose: Retarget stdio to CMSIS UART + * + *---------------------------------------------------------------------------*/ + +#ifdef CMSIS_target_header +#include CMSIS_target_header +#else +#include "Driver_USART.h" +#endif + +#ifndef RETARGET_STDIO_UART +#error "RETARGET_STDIO_UART not defined!" +#endif + +/* Compile-time configuration */ +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif + +/* References to the external retarget functions */ +extern int stdio_init (void); +extern int stderr_putchar (int ch); +extern int stdout_putchar (int ch); +extern int stdin_getchar (void); + +/* Reference to the underlying USART driver */ +#ifndef CMSIS_target_header +extern ARM_DRIVER_USART ARM_Driver_USART_(RETARGET_STDIO_UART); +#endif +#define ptrUSART (&ARM_Driver_USART_(RETARGET_STDIO_UART)) + +/** + Initialize stdio + + \return 0 on success, or -1 on error. +*/ +int stdio_init (void) { + + if (ptrUSART->Initialize(NULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | + ARM_USART_DATA_BITS_8 | + ARM_USART_PARITY_NONE | + ARM_USART_STOP_BITS_1 | + ARM_USART_FLOW_CONTROL_NONE, + UART_BAUDRATE) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_RX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_TX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + return 0; +} + +/** + Put a character to the stderr + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stderr_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Put a character to the stdout + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stdout_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Get a character from the stdio + + \return The next character from the input, or -1 on read error. +*/ +int stdin_getchar (void) { + uint8_t buf[1]; + + if (ptrUSART->Receive(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().rx_busy != 0U); + + return (int)buf[0]; +} \ No newline at end of file diff --git a/board/Corstone-315/sse315_memmap_ns.h b/board/Corstone-315/sse315_memmap_ns.h new file mode 100644 index 0000000..354f78b --- /dev/null +++ b/board/Corstone-315/sse315_memmap_ns.h @@ -0,0 +1,102 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE320_MEMMAP_NS_H +#define SSE320_MEMMAP_NS_H + +/*============================================================================*/ +/* NON-SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Non-Secure */ +#define ITCM_NS_BASE 0x00000000 +#define ITCM_NS_SIZE 0x00008000 /* 32KB */ +#define ITCM_NS_LIMIT (ITCM_NS_BASE + ITCM_NS_SIZE - 1) + +/* FPGA SRAM - Non-Secure */ +#define FPGA_SRAM_NS_BASE 0x01000000 +#define FPGA_SRAM_NS_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_NS_LIMIT (FPGA_SRAM_NS_BASE + FPGA_SRAM_NS_SIZE - 1) + +/* DMA ITCM - Non-Secure */ +#define DMA_ITCM_NS_BASE 0x0A000000 +#define DMA_ITCM_NS_SIZE 0x00008000 /* 32KB */ +#define DMA_ITCM_NS_LIMIT (DMA_ITCM_NS_BASE + DMA_ITCM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Non-Secure */ +#define DTCM_NS_BASE 0x20000000 +#define DTCM_NS_SIZE 0x00008000 /* 32KB */ +#define DTCM_NS_LIMIT (DTCM_NS_BASE + DTCM_NS_SIZE - 1) + +/* SRAM VM0 - Non-Secure */ +#define SRAM_VM0_NS_BASE 0x21000000 +#define SRAM_VM0_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_NS_LIMIT (SRAM_VM0_NS_BASE + SRAM_VM0_NS_SIZE - 1) + +/* SRAM VM1 - Non-Secure */ +#define SRAM_VM1_NS_BASE 0x21200000 +#define SRAM_VM1_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_NS_LIMIT (SRAM_VM1_NS_BASE + SRAM_VM1_NS_SIZE - 1) + +/* DMA DTCM - Non-Secure */ +#define DMA_DTCM_NS_BASE 0x24000000 +#define DMA_DTCM_NS_SIZE 0x00008000 /* 32KB */ +#define DMA_DTCM_NS_LIMIT (DMA_DTCM_NS_BASE + DMA_DTCM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Non-Secure */ +#define QSPI_FLASH_NS_BASE 0x28000000 +#define QSPI_FLASH_NS_SIZE 0x08000000 /* 128MB */ +#define QSPI_FLASH_NS_LIMIT (QSPI_FLASH_NS_BASE + QSPI_FLASH_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 0 - Non-Secure */ +#define DDR4_0_NS_BASE 0x60000000 +#define DDR4_0_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_0_NS_LIMIT (DDR4_0_NS_BASE + DDR4_0_NS_SIZE - 1) + +/* DDR4 Region 2 - Non-Secure */ +#define DDR4_2_NS_BASE 0x80000000 +#define DDR4_2_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_2_NS_LIMIT (DDR4_2_NS_BASE + DDR4_2_NS_SIZE - 1) + +/* DDR4 Region 4 - Non-Secure */ +#define DDR4_4_NS_BASE 0xA0000000 +#define DDR4_4_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_4_NS_LIMIT (DDR4_4_NS_BASE + DDR4_4_NS_SIZE - 1) + +/* DDR4 Region 6 - Non-Secure */ +#define DDR4_6_NS_BASE 0xC0000000 +#define DDR4_6_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_6_NS_LIMIT (DDR4_6_NS_BASE + DDR4_6_NS_SIZE - 1) + +#endif /* SSE320_MEMMAP_NS_H */ diff --git a/board/Corstone-315/sse315_memmap_s.h b/board/Corstone-315/sse315_memmap_s.h new file mode 100644 index 0000000..42d7691 --- /dev/null +++ b/board/Corstone-315/sse315_memmap_s.h @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE320_MEMMAP_S_H +#define SSE320_MEMMAP_S_H + +/*============================================================================*/ +/* SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Secure */ +#define ITCM_S_BASE 0x10000000 +#define ITCM_S_SIZE 0x00008000 /* 32KB */ +#define ITCM_S_LIMIT (ITCM_S_BASE + ITCM_S_SIZE - 1) + +/* Boot ROM - Secure (Startup) */ +#define BOOT_ROM_S_BASE 0x11000000 +#define BOOT_ROM_S_SIZE 0x00020000 /* 128KB */ +#define BOOT_ROM_S_LIMIT (BOOT_ROM_S_BASE + BOOT_ROM_S_SIZE - 1) + +/* FPGA SRAM - Secure */ +#define FPGA_SRAM_S_BASE 0x12000000 +#define FPGA_SRAM_S_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_S_LIMIT (FPGA_SRAM_S_BASE + FPGA_SRAM_S_SIZE - 1) + +/* DMA ITCM - Secure */ +#define DMA_ITCM_S_BASE 0x1A000000 +#define DMA_ITCM_S_SIZE 0x00008000 /* 32KB */ +#define DMA_ITCM_S_LIMIT (DMA_ITCM_S_BASE + DMA_ITCM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Secure */ +#define DTCM_S_BASE 0x30000000 +#define DTCM_S_SIZE 0x00008000 /* 32KB */ +#define DTCM_S_LIMIT (DTCM_S_BASE + DTCM_S_SIZE - 1) + +/* SRAM VM0 - Secure */ +#define SRAM_VM0_S_BASE 0x31000000 +#define SRAM_VM0_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_S_LIMIT (SRAM_VM0_S_BASE + SRAM_VM0_S_SIZE - 1) + +/* SRAM VM1 - Secure */ +#define SRAM_VM1_S_BASE 0x31200000 +#define SRAM_VM1_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_S_LIMIT (SRAM_VM1_S_BASE + SRAM_VM1_S_SIZE - 1) + +/* DMA DTCM - Secure */ +#define DMA_DTCM_S_BASE 0x34000000 +#define DMA_DTCM_S_SIZE 0x00008000 /* 32KB */ +#define DMA_DTCM_S_LIMIT (DMA_DTCM_S_BASE + DMA_DTCM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_S_BASE 0x38000000 +#define QSPI_FLASH_S_SIZE 0x08000000 /* 128MB */ +#define QSPI_FLASH_S_LIMIT (QSPI_FLASH_S_BASE + QSPI_FLASH_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 1 - Secure */ +#define DDR4_1_S_BASE 0x70000000 +#define DDR4_1_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_1_S_LIMIT (DDR4_1_S_BASE + DDR4_1_S_SIZE - 1) + +/* DDR4 Region 3 - Secure */ +#define DDR4_3_S_BASE 0x90000000 +#define DDR4_3_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_3_S_LIMIT (DDR4_3_S_BASE + DDR4_3_S_SIZE - 1) + +/* DDR4 Region 5 - Secure */ +#define DDR4_5_S_BASE 0xB0000000 +#define DDR4_5_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_5_S_LIMIT (DDR4_5_S_BASE + DDR4_5_S_SIZE - 1) + +/* DDR4 Region 7 - Secure */ +#define DDR4_7_S_BASE 0xD0000000 +#define DDR4_7_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_7_S_LIMIT (DDR4_7_S_BASE + DDR4_7_S_SIZE - 1) + +#endif /* SSE320_MEMMAP_S_H */ diff --git a/board/Corstone-315/vsi/python/arm_vsi0.py b/board/Corstone-315/vsi/python/arm_vsi0.py new file mode 100644 index 0000000..e1a7bfc --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi0.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 0 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi0_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6000) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/arm_vsi1.py b/board/Corstone-315/vsi/python/arm_vsi1.py new file mode 100644 index 0000000..f1271b5 --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi1.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 1 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi1_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6001) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/arm_vsi4.py b/board/Corstone-315/vsi/python/arm_vsi4.py new file mode 100644 index 0000000..e15edf8 --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi4.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 4 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi4_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6004) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/arm_vsi5.py b/board/Corstone-315/vsi/python/arm_vsi5.py new file mode 100644 index 0000000..631f74d --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi5.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 5 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi5_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6005) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/arm_vsi6.py b/board/Corstone-315/vsi/python/arm_vsi6.py new file mode 100644 index 0000000..58b1184 --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi6.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 6 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi6_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6006) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/arm_vsi7.py b/board/Corstone-315/vsi/python/arm_vsi7.py new file mode 100644 index 0000000..cd32ab8 --- /dev/null +++ b/board/Corstone-315/vsi/python/arm_vsi7.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 7 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi7_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6007) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-315/vsi/python/vsi_audio.py b/board/Corstone-315/vsi/python/vsi_audio.py new file mode 100644 index 0000000..a71574a --- /dev/null +++ b/board/Corstone-315/vsi/python/vsi_audio.py @@ -0,0 +1,543 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) audio server. +# It allows configuration, streaming, and audio data transfer operations, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Audio:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Audio:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class AudioClient: + """ + Client for communicating with the VSI audio server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive audio data, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Audio format codes + self.PCM_S8 = 0 + self.PCM_S16LE = 1 + self.PCM_S24LE = 2 + self.PCM_S32LE = 3 + self.PCM_F32LE = 4 + + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI audio server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the audio stream (input/output). + Args: + mode: 1 for input, 2 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the audio streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the audio stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters on the server. + Args: + channels: Number of audio channels (1=mono, 2=stereo). + sample_rate: Sample rate in Hz (e.g., 44100, 48000). + sample_bits: Bit depth (8, 16, 24, 32). + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, channels, sample_rate, sample_bits]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the audio stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the audio stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readAudio(self, size): + """ + Request audio data from the server. + Args: + size: Number of bytes to read. + Returns: + tuple: (data, eos) where data is a Bytearray of audio data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.AUDIO_READ, size]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeAudio(self, data): + """ + Send audio data to the server. + Args: + data: Bytearray of audio data to write. + Returns: + None + """ + self.conn.send([self.AUDIO_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +CHANNELS = 1 # Regs[4] // Number of audio channels +SAMPLE_RATE = 16000 # Regs[5] // Sample rate +SAMPLE_BITS = 16 # Regs[6] // Bits per sample + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Audio.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Audio.configureStream(CHANNELS, SAMPLE_RATE, SAMPLE_BITS) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Audio.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Audio.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Audio.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Audio.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = CHANNELS + elif index == 5: + value = SAMPLE_RATE + elif index == 6: + value = SAMPLE_BITS + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + CHANNELS = value + elif index == 5: + SAMPLE_RATE = value + elif index == 6: + SAMPLE_BITS = value + + return value diff --git a/board/Corstone-315/vsi/python/vsi_audio_server.py b/board/Corstone-315/vsi/python/vsi_audio_server.py new file mode 100644 index 0000000..dafa594 --- /dev/null +++ b/board/Corstone-315/vsi/python/vsi_audio_server.py @@ -0,0 +1,691 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Server module + +try: + import argparse + import ipaddress + import logging + import time + import wave + from multiprocessing.connection import Listener + from pathlib import Path + + import pyaudio + import numpy as np +except ImportError as err: + print(f"VSI:Audio:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Audio:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Audio Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6001) +default_authkey = 'vsi_audio' + +# Supported file extensions +supported_files = ['wav'] + +# Mode Input/Output +MODE_AUDIO_NONE = 0 +MODE_AUDIO_INPUT = 1 +MODE_AUDIO_OUTPUT = 2 + +class AudioServer: + """Implements a TCP server for audio streaming and sample I/O. + + Supports both audio files and microphone/speaker devices as input/output. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing audio data), and performs the requested audio + operations using PyAudio and wave modules. + """ + def __init__(self, address, authkey): + """ + Initialize the AudioServer. + + Sets up command codes, audio format constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.eos = False + self.stream = None + self.wave_file = None + self.pyaudio_obj = pyaudio.PyAudio() + self.audio_buffer = bytearray() + self.chunk_size = 1024 + + # Stream configuration + self.channels = None + self.sample_rate = None + self.sample_bits = None + + def _setMode(self, mode): + """ + Set the stream mode to input (microphone/file) or output (speakers/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_AUDIO_INPUT: + self.mode = MODE_AUDIO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_AUDIO_OUTPUT: + self.mode = MODE_AUDIO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_AUDIO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_audio_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in supported_files: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_AUDIO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_AUDIO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters. + + Args: + channels: The number of audio channels (1=mono, 2=stereo). + sample_rate: The sample rate in Hz (8000, 16000, 44100, 48000). + sample_bits: The bit depth (8, 16, 24, 32). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits}") + + if channels <= 0 or sample_rate <= 0 or sample_bits <= 0: + logger.error(f"_configureStream: invalid argument (channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits})") + return False + + if sample_bits not in [8, 16, 24, 32]: + logger.error(f"_configureStream: unsupported sample_bits={sample_bits}") + return False + + self.channels = channels + self.sample_rate = sample_rate + self.sample_bits = sample_bits + + logger.info(f"_configureStream: stream configured to {self.channels} channels, {self.sample_rate}Hz, {self.sample_bits} bits") + + return True + + def _get_pyaudio_format(self): + """Get PyAudio format based on sample bits.""" + if self.sample_bits == 8: + return pyaudio.paUInt8 + elif self.sample_bits == 16: + return pyaudio.paInt16 + elif self.sample_bits == 24: + return pyaudio.paInt24 + elif self.sample_bits == 32: + return pyaudio.paInt32 + else: + return pyaudio.paInt16 # default + + def _scan_audio_devices(self): + """ + Scan and log available audio devices, separating input and output devices. + Returns: + Default device index for the current mode. + """ + if self.pyaudio_obj is None: + logger.error(" _scan_audio_devices: PyAudio object is not initialized") + return 0 + + logger.info("=== Available Audio Devices ===") + device_count = self.pyaudio_obj.get_device_count() + + input_devices = [] + output_devices = [] + + # Scan all devices + for i in range(device_count): + try: + info = self.pyaudio_obj.get_device_info_by_index(i) + host_api_info = self.pyaudio_obj.get_host_api_info_by_index(info['hostApi']) + + device_info = { + 'index': i, + 'name': info['name'], + 'max_input_channels': info['maxInputChannels'], + 'max_output_channels': info['maxOutputChannels'], + 'default_sample_rate': info['defaultSampleRate'], + 'host_api': host_api_info['name'] + } + + # Categorize devices + if info['maxInputChannels'] > 0: + input_devices.append(device_info) + if info['maxOutputChannels'] > 0: + output_devices.append(device_info) + + except Exception as e: + logger.warning(f"Device {i}: Error reading device info - {e}") + + # Retrieve default devices + try: + default_input = self.pyaudio_obj.get_default_input_device_info() + default_output = self.pyaudio_obj.get_default_output_device_info() + except Exception as e: + logger.warning(f"Error getting default devices: {e}") + + if (self.mode == MODE_AUDIO_INPUT): + # Log input devices + logger.info("--- INPUT DEVICES ---") + if input_devices: + for device in input_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Input Channels: {device['max_input_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No input devices found") + + logger.info(f"Default Input Device: {default_input['index']} - {default_input['name']}") + + rval = default_input['index'] + + if (self.mode == MODE_AUDIO_OUTPUT): + # Log output devices + logger.debug("--- OUTPUT DEVICES ---") + if output_devices: + for device in output_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Output Channels: {device['max_output_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No output devices found") + + logger.info(f"Default Output Device: {default_output['index']} - {default_output['name']}") + + rval = default_output['index'] + + return rval + + def _audio_callback_input(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio input stream. + """ + logger.debug(f"_audio_callback_input: received {len(in_data)} bytes") + + self.audio_buffer.extend(in_data) + return (None, pyaudio.paContinue) + + def _audio_callback_output(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio output stream. + """ + logger.debug(f"_audio_callback_output: requested {frame_count} frames") + + bytes_needed = frame_count * self.channels * (self.sample_bits // 8) + if len(self.audio_buffer) >= bytes_needed: + data = bytes(self.audio_buffer[:bytes_needed]) + del self.audio_buffer[:bytes_needed] + else: + # Not enough data, return silence + data = b'\x00' * bytes_needed + return (data, pyaudio.paContinue) + + def _enableStream(self): + """ + Enable the audio stream for input (microphone/file) or output (file/speakers). + + Initializes the PyAudio stream or wave file as needed. + Returns: + None + """ + if self.mode != MODE_AUDIO_INPUT and self.mode != MODE_AUDIO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.audio_buffer.clear() + + try: + if self.filename == None: + # Use microphone/speakers + if self.pyaudio_obj is None: + logger.error("_enableStream: PyAudio object is not initialized") + return + + audio_format = self._get_pyaudio_format() + + if self.mode == MODE_AUDIO_INPUT: + logger.debug("_enableStream: use microphone for input streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + input=True, + input_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_input + ) + self.stream.start_stream() + + elif self.mode == MODE_AUDIO_OUTPUT: + logger.debug("_enableStream: use speakers for output streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + output=True, + output_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_output + ) + self.stream.start_stream() + + logger.info(f"_enableStream: audio device stream properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + else: + # Set file name string for audio file + file = str(self.filename.absolute()) + + logger.debug(f"_enableStream: use audio file: {file}") + + if self.mode == MODE_AUDIO_INPUT: + self.wave_file = wave.open(file, 'rb') + + # Verify file properties match configuration + file_channels = self.wave_file.getnchannels() + file_rate = self.wave_file.getframerate() + file_bits = self.wave_file.getsampwidth() * 8 + + if (file_channels != self.channels or file_rate != self.sample_rate or file_bits != self.sample_bits): + logger.warning(f"_enableStream: file properties ({file_channels}ch, {file_rate}Hz, {file_bits}bit) " + f"don't match configured ({self.channels}ch, {self.sample_rate}Hz, {self.sample_bits}bit)") + + logger.info(f"_enableStream: input file properties: channels={file_channels}, rate={file_rate}, bits={file_bits}") + + elif self.mode == MODE_AUDIO_OUTPUT: + self.wave_file = wave.open(file, 'wb') + self.wave_file.setnchannels(self.channels) + self.wave_file.setsampwidth(self.sample_bits // 8) + self.wave_file.setframerate(self.sample_rate) + + logger.info(f"_enableStream: output file properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + self.active = True + logger.info("_enableStream: stream enabled") + + except Exception as e: + logger.error(f"_enableStream: failed to enable stream: {e}") + self._disableStream() + + def _disableStream(self): + """ + Disable the audio stream and release resources. + + Returns: + None + """ + self.active = False + + try: + if self.stream is not None: + if self.stream.is_active(): + self.stream.stop_stream() + self.stream.close() + self.stream = None + + if self.pyaudio_obj is not None: + self.pyaudio_obj.terminate() + self.pyaudio_obj = None + + if self.wave_file is not None: + self.wave_file.close() + self.wave_file = None + + except Exception as e: + logger.error(f"_disableStream: error during cleanup: {e}") + + logger.info("_disableStream: stream disabled") + + def _readAudio(self, size): + """ + Read audio data from the current source. + + Args: + size: Number of bytes to read. + Returns: + audio_data: The read audio data as a bytearray, or empty if no data is available. + """ + logger.debug(f"_readAudio: size={size} bytes") + + audio_data = bytearray() + + if not self.active: + logger.error("_readAudio: stream not active") + return audio_data + + if self.eos: + logger.debug("_readAudio: end of stream") + return audio_data + + try: + if self.filename == None: + # Read from microphone buffer + while len(self.audio_buffer) < size: + # Wait for enough data + time.sleep(0.01) # Wait 10ms + + # Now we have enough data + audio_data = bytearray(self.audio_buffer[:size]) + del self.audio_buffer[:size] + + logger.debug(f"_readAudio: read {len(audio_data)} bytes from microphone buffer") + + else: + # Read from wave file + frames_to_read = size // (self.channels * (self.sample_bits // 8)) + frames_data = self.wave_file.readframes(frames_to_read) + + if len(frames_data) > 0: + audio_data = bytearray(frames_data) + logger.debug(f"_readAudio: read {len(audio_data)} bytes from file") + else: + self.eos = True + logger.debug("_readAudio: end of file reached") + + except Exception as e: + logger.error(f"_readAudio: error reading audio data: {e}") + + return audio_data + + def _writeAudio(self, data): + """ + Write audio data to the output destination (file or speakers). + + Args: + data: The input audio data as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeAudio: audio data size={len(data)} bytes") + + if not self.active: + logger.error("_writeAudio: stream not active") + return + + try: + if self.filename == None: + # Write to speakers buffer + self.audio_buffer.extend(data) + logger.debug("_writeAudio: added data to speaker buffer") + + else: + # Write to wave file + self.wave_file.writeframes(data) + logger.debug("_writeAudio: wrote data to file") + + except Exception as e: + logger.error(f"_writeAudio: error writing audio data: {e}") + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write audio, close server. + Sends responses or audio data as appropriate. + """ + logger.info("Audio server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.AUDIO_READ: + size = payload[0] + audio_data = self._readAudio(size) + conn.send_bytes(audio_data) + conn.send(self.eos) + + elif cmd == self.AUDIO_WRITE: + audio_data = conn.recv_bytes() + self._writeAudio(audio_data) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + def stop(self): + """ + Stop the audio server. + + Releases all resources. + Returns: + None + """ + self._disableStream() + self.listener.close() + logger.info("Audio server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the audio server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Audio Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = AudioServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-315/vsi/python/vsi_video.py b/board/Corstone-315/vsi/python/vsi_video.py new file mode 100644 index 0000000..47a2af2 --- /dev/null +++ b/board/Corstone-315/vsi/python/vsi_video.py @@ -0,0 +1,547 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) video server. +# It allows configuration, streaming, and frame transfer operations for video data, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Video:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Video:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class VideoClient: + """ + Client for communicating with the VSI video server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive frames, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space codes + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI video server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the video stream (input/output). + Args: + mode: 0 for input, 1 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the video streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the video stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, frame_width, frame_height, frame_rate, color_format): + """ + Configure the video stream parameters on the server. + Args: + frame_width: Width of the video frame. + frame_height: Height of the video frame. + frame_rate: Frame rate in frames per second. + color_format: Color format code. + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, frame_width, frame_height, frame_rate, color_format]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the video stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the video stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readFrame(self): + """ + Request a video frame from the server. + Returns: + tuple: (data, eos) where data is a Bytearray of frame data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.FRAME_READ]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeFrame(self, data): + """ + Send a video frame to the server. + Args: + data: Bytearray of frame data to write. + Returns: + None + """ + self.conn.send([self.FRAME_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +FRAME_WIDTH = 300 # Regs[4] // Requested frame width +FRAME_HEIGHT = 300 # Regs[5] // Requested frame height +FRAME_RATE = 0 # Regs[6] // Frame rate +FRAME_COLOR = 0 # Regs[7] // Frame color space + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Video.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Video.configureStream(FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Video.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Video.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Video.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Video.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = FRAME_WIDTH + elif index == 5: + value = FRAME_HEIGHT + elif index == 6: + value = FRAME_RATE + elif index == 7: + value = FRAME_COLOR + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + FRAME_WIDTH = value + elif index == 5: + FRAME_HEIGHT = value + elif index == 6: + FRAME_RATE = value + elif index == 7: + FRAME_COLOR = value + + return value diff --git a/board/Corstone-315/vsi/python/vsi_video_server.py b/board/Corstone-315/vsi/python/vsi_video_server.py new file mode 100644 index 0000000..3699eb3 --- /dev/null +++ b/board/Corstone-315/vsi/python/vsi_video_server.py @@ -0,0 +1,785 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Server module + +try: + import argparse + import ipaddress + import logging + from multiprocessing.connection import Listener + from pathlib import Path + + import cv2 + import numpy as np +except ImportError as err: + print(f"VSI:Video:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Video:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Video Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6000) +default_authkey = 'vsi_video' + +# Supported file extensions +video_file_extensions = ('wmv', 'avi', 'mp4') +image_file_extensions = ('bmp', 'png', 'jpg') +video_fourcc = {'wmv' : 'WMV1', 'avi' : 'MJPG', 'mp4' : 'mp4v'} + +# Mode Input/Output +MODE_VIDEO_NONE = 0 +MODE_VIDEO_INPUT = 1 +MODE_VIDEO_OUTPUT = 2 + +class VideoServer: + """Implements a TCP server for video streaming and frame I/O. + + Supports both video and image files as input/output, and can interface with a camera device. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing frames), and performs the requested video + operations using OpenCV. + """ + def __init__(self, address, authkey): + """ + Initialize the VideoServer. + + Sets up command codes, color space constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.video = True + self.stream = None + self.frame_ratio = 0 + self.frame_drop = 0 + self.eos = False + # Stream configuration + self.frame_width = None + self.frame_height = None + self.frame_color = None + self.frame_rate = None + + + def _setMode(self, mode): + """ + Set the stream mode to input (camera/file) or output (display/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_VIDEO_INPUT: + self.mode = MODE_VIDEO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_VIDEO_OUTPUT: + self.mode = MODE_VIDEO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_VIDEO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_video_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in video_file_extensions + image_file_extensions: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_VIDEO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_VIDEO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, frame_width, frame_height, frame_rate, frame_color): + """ + Configure the video stream parameters. + + Args: + frame_width: The desired frame width in pixels. + frame_height: The desired frame height in pixels. + frame_rate: The desired frame rate in frames per second. + frame_color: The desired frame color space (one of the defined constants). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: frame_width={frame_width}, frame_height={frame_height}, frame_rate={frame_rate}, frame_color={frame_color}") + + if (frame_width == 0 or frame_height == 0 or frame_rate == 0): + logger.error(f"_configureStream: invalid argument (width={frame_width}, height={frame_height}, rate={frame_rate})") + return False + if frame_color not in (self.GRAYSCALE8, self.RGB888, self.BGR565, self.YUV420, self.NV12, self.NV21): + logger.error(f"_configureStream: invalid argument (color={frame_color})") + return False + + self.frame_width = frame_width + self.frame_height = frame_height + self.frame_rate = frame_rate + self.frame_color = frame_color + + logger.info(f"_configureStream: stream configured to {self.frame_width}x{self.frame_height}, fps={self.frame_rate}, color={self.frame_color}") + + return True + + def _scan_video_devices(self): + """ + Scan and log available video input devices. + Returns: + Default device index for the current mode. + """ + logger.info("=== Available Video Devices ===") + + available_devices = [] + + # Test device indices 0-1 (covers built-in webcam + external camera) + for device_index in range(2): + try: + cap = cv2.VideoCapture(device_index) + if cap.isOpened(): + + # Get device properties + width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + + device_info = { + 'index': device_index, + 'width': width, + 'height': height, + 'fps': fps, + } + available_devices.append(device_info) + + logger.info(f"Device {device_index}: {width}x{height} @ {fps:.1f}fps") + + cap.release() + except Exception as e: + logger.error(f"Error accessing device {device_index}: {e}") + + if not available_devices: + logger.warning("No video devices found") + return -1 + else: + logger.info(f"Found {len(available_devices)} input device(s)") + logger.info(f"Default Input Device: 0") + + return 0 + + def _enableStream(self): + """ + Enable the video stream for input (camera/file) or output (file/display). + + Initializes the OpenCV VideoCapture or VideoWriter as needed. + Handles both new and existing files, and sets up frame dropping if input FPS > requested FPS. + Returns: + None + """ + + if self.mode != MODE_VIDEO_INPUT and self.mode != MODE_VIDEO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.frame_ratio = 0 + self.frame_drop = 0 + + if self.stream is not None: + self.stream.release() + self.stream = None + + if self.filename == None: + self.video = True + + if self.video: + if self.mode == MODE_VIDEO_INPUT: + # Input mode: read from camera or video file + if self.filename == None: + # No filename specified: use camera interface + logger.debug("_enableStream: use camera interface for input streaming") + self.stream = cv2.VideoCapture(self.device) + + if not self.stream.isOpened(): + logger.error("_enableStream: failed to open Camera interface") + return + else: + # Filename specified: use video file + logger.debug("_enableStream: use file interface for input streaming") + self.stream = cv2.VideoCapture(self.filename) + + # Display stream properties + logger.info(f"_enableStream: source stream properties: width={self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)}, height={self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)}, fps={self.stream.get(cv2.CAP_PROP_FPS)}") + + # Get the video stream FPS + video_fps = self.stream.get(cv2.CAP_PROP_FPS) + + if video_fps > self.frame_rate: + self.frame_ratio = video_fps / self.frame_rate + logger.debug(f"_enableStream: source/target frame ratio={self.frame_ratio}") + + elif self.mode == MODE_VIDEO_OUTPUT: + # Output mode: write to video file or display window + if self.filename != None: + # Filename specified: output to file + logger.debug("_enableStream: output stream to a file") + + extension = self.filename.suffix.lstrip('.').lower() + fourcc = cv2.VideoWriter_fourcc(*f'{video_fourcc[extension]}') + + self.stream = cv2.VideoWriter(self.filename, fourcc, self.frame_rate, (self.frame_width, self.frame_height)) + else: + logger.debug("_enableStream: output stream to display window") + + self.active = True + logger.info("_enableStream: stream enabled") + + def _disableStream(self): + """ + Disable the video stream and release OpenCV resources. + + For input streams, saves the current frame index for resuming later. + Returns: + None + """ + self.active = False + if self.stream is not None: + # Clean-up stream resources and invalidate object + self.stream.release() + self.stream = None + + logger.info("_disableStream: stream disabled") + + def __cropFrame(self, frame, target_aspect_ratio): + """ + Crop the input frame to match the specified aspect ratio. + + Args: + frame: The input frame (as NumPy array) to be cropped. + aspect_ratio: The target aspect ratio (width/height). + Returns: + frame: The cropped frame. + """ + logger.debug(f"__cropFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_aspect_ratio={target_aspect_ratio}") + + # NumPY array shape is (height, width, channels) + frame_h = frame.shape[0] + frame_w = frame.shape[1] + + frame_aspect_ratio = frame_w / frame_h + + if frame_aspect_ratio > target_aspect_ratio: + # Frame is wider than target -> crop left and right + new_w = int(frame_h * target_aspect_ratio) + left = (frame_w - new_w) // 2 + right = left + new_w + cropped = frame[:, left:right] + else: + # Frame is taller than target -> crop top and bottom + new_h = int(frame_w / target_aspect_ratio) + top = (frame_h - new_h) // 2 + bottom = top + new_h + cropped = frame[top:bottom, :] + + logger.debug(f"__cropFrame: cropped_size=({cropped.shape[1]}, {cropped.shape[0]})") + + return cropped + + def __resizeFrame(self, frame, target_width, target_height): + """ + Resize the input frame to the target width and height. + + Args: + frame: The input frame (as NumPy array) to be resized. + target_width: The target width in pixels. + target_height: The target height in pixels. + Returns: + frame: The resized frame. + """ + logger.debug(f"__resizeFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_size=({target_width}, {target_height})") + + try: + frame = cv2.resize(frame, (target_width, target_height)) + except Exception as e: + logger.error(f"Error in resizeFrame(): {e}") + + logger.debug(f"__resizeFrame: resized_size=({frame.shape[1]}, {frame.shape[0]})") + + return frame + + def __convertToBGR(self, frame): + """ + Convert the input frame to BGR color space if needed. + + Args: + frame: The input frame (as NumPy array) to be converted. + Returns: + frame: The converted frame in BGR color space. + """ + if self.frame_color == self.RGB888: + # Convert RGB to BGR + logger.debug(f"__convertToBGR: converting frame from RGB to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) + elif self.frame_color == self.GRAYSCALE8: + # Convert Grayscale to BGR + logger.debug(f"__convertToBGR: converting frame from Grayscale to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) + elif self.frame_color == self.BGR565: + # Convert BGR565 to BGR + logger.debug(f"__convertToBGR: converting frame from BGR565 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR5652BGR) + elif self.frame_color == self.YUV420: + # Convert YUV420 to BGR + logger.debug(f"__convertToBGR: converting frame from YUV420 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_I420) + elif self.frame_color == self.NV12: + # Convert NV12 to BGR + logger.debug(f"__convertToBGR: converting frame from NV12 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV12) + elif self.frame_color == self.NV21: + # Convert NV21 to BGR + logger.debug(f"__convertToBGR: converting frame from NV21 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV21) + + return frame + + def __convertFromBGR(self, frame): + """ + Convert the input BGR frame to the specified color space if needed. + + Args: + frame: The input frame (as NumPy array in BGR color space) to be converted. + Returns: + frame: The converted frame in the specified color space. + """ + if self.frame_color == self.RGB888: + # Convert BGR to RGB + logger.debug(f"__convertFromBGR: converting frame from BGR to RGB") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + elif self.frame_color == self.GRAYSCALE8: + # Convert BGR to Grayscale + logger.debug(f"__convertFromBGR: converting frame from BGR to Grayscale") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + elif self.frame_color == self.BGR565: + # Convert BGR to BGR565 + logger.debug(f"__convertFromBGR: converting frame from BGR to BGR565") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGR565) + elif self.frame_color == self.YUV420: + # Convert BGR to YUV420 + logger.debug(f"__convertFromBGR: converting frame from BGR to YUV420") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420) + elif self.frame_color == self.NV12: + # Convert BGR to NV12 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV12") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV12) + elif self.frame_color == self.NV21: + # Convert BGR to NV21 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV21") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV21) + + return frame + + # Read frame from source + def _readFrame(self): + """Read a single frame from the current video or image source. + + If the stream is not active or end-of-stream is reached, returns an empty bytearray. + For video sources, handles frame dropping to match requested frame rate. + For image sources, reads the image once and sets end-of-stream. + Resizes and converts color space as needed. + Returns: + frame: The read frame as a bytearray, or empty if no frame is available. + """ + frame = bytearray() + + # If the stream is not active, return empty frame + if not self.active: + logger.error("_readFrame: stream not active") + return frame + + # If end-of-stream has been reached, return empty frame + if self.eos: + logger.debug("_readFrame: end of stream reached") + return frame + + if self.video: + # Video source, read frame from the video stream + _, frame_in = self.stream.read() # Frame is numpy.ndarray, (height, width, channels), dtype=uint8 + + if frame_in is not None: + logger.debug(f"_readFrame: frame captured, size=({frame_in.shape[1]}, {frame_in.shape[0]})") + + # Handle frame dropping if input FPS > requested FPS + if self.frame_ratio > 1: + # Accumulate fractional frames to drop + self.frame_drop += (self.frame_ratio - 1) + + if self.frame_drop > 1: + logger.debug(f"_readFrame: frames to drop={self.frame_drop}") + drop = int(self.frame_drop // 1) + + # Drop the required number of frames to match requested FPS + for i in range(drop): + _, _ = self.stream.read() + logger.debug(f"_readFrame: frames dropped={drop}") + self.frame_drop -= drop + logger.debug(f"_readFrame: frames left to drop={self.frame_drop}") + else: + # Frame not read, mark end-of-stream + self.eos = True + logger.debug("_readFrame: end of stream.") + else: + # For image sources, read the image once and set end-of-stream + frame_in = cv2.imread(self.filename) + self.eos = True + logger.debug("_readFrame: end of stream.") + + if frame_in is not None: + target_width = self.frame_width + target_height = self.frame_height + + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size aspect ratio + target_aspect_ratio = target_width / target_height + frame_aspect_ratio = frame_in_width / frame_in_height + + if not np.isclose(frame_aspect_ratio, target_aspect_ratio, rtol=1e-3): + logger.debug(f"_readFrame: frame aspect ratio {frame_aspect_ratio:.2f} does not match target {target_aspect_ratio:.2f}, cropping frame") + frame_in = self.__cropFrame(frame_in, target_aspect_ratio) + + # Update frame size after cropping + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size + if (frame_in_width != target_width) or (frame_in_height != target_height): + logger.debug(f"_readFrame: frame size ({frame_in_width}, {frame_in_height}) does not match target ({target_width}, {target_height}), resizing frame") + frame_in = self.__resizeFrame(frame_in, target_width, target_height) + + # Convert frame color space to target color space + frame_in = self.__convertFromBGR(frame_in) + + # Convert the frame to a bytearray for transmission + frame = bytearray(frame_in.tobytes()) + + return frame + + def _writeFrame(self, frame): + """ + Write a frame to the output destination (file or display window). + + If filename is empty, displays the frame in a window. + If filename is set and video mode, writes frame to video file. + If filename is set and image mode, saves frame as image file. + Args: + frame: The input frame as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeFrame: frame size={len(frame)} bytes") + + # If the stream is not active, do nothing + if not self.active: + logger.error("_writeFrame: stream not active") + return + + try: + # Decode the frame from bytearray to a NumPy array + decoded_frame = np.frombuffer(frame, dtype=np.uint8) + + # Reshape the decoded frame to match the target resolution + decoded_frame = decoded_frame.reshape((self.frame_height, self.frame_width, 3)) + logger.debug(f"_writeFrame: decoded frame size=({decoded_frame.shape[1]}, {decoded_frame.shape[0]})") + + # Convert color space to BGR + frame_out = self.__convertToBGR(decoded_frame) + + if self.filename == None: + logger.debug("_writeFrame: display frame in window") + # If no filename, display the frame in a window + cv2.imshow(self.filename, frame_out) + cv2.waitKey(10) + else: + if self.video: + logger.debug("_writeFrame: write frame to video file") + # Write frame to video file + self.stream.write(np.uint8(frame_out)) + else: + logger.debug("_writeFrame: write frame as image file") + # Write frame as image file + cv2.imwrite(self.filename, frame_out) + + except Exception as e: + # Output exception debug information but continue + logger.error(f"Exception in _writeFrame: {type(e).__name__}: {e}", exc_info=True) + pass + + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write frames, close server. + Sends responses or frame data as appropriate. + """ + logger.info("Video server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2], payload[3]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.FRAME_READ: + frame = self._readFrame() + conn.send_bytes(frame) + conn.send(self.eos) + + elif cmd == self.FRAME_WRITE: + frame = conn.recv_bytes() + self._writeFrame(frame) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + + def stop(self): + """ + Stop the video server. + + Releases all resources and closes any open windows. + Returns: + None + """ + self._disableStream() + if (self.mode == MODE_VIDEO_OUTPUT) and (self.filename == None): + try: + cv2.destroyAllWindows() + except Exception: + pass + self.listener.close() + logger.info("Video server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the video server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Video Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = VideoServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-320/Board-U85.clayer.yml b/board/Corstone-320/Board-U85.clayer.yml new file mode 100644 index 0000000..eb31da0 --- /dev/null +++ b/board/Corstone-320/Board-U85.clayer.yml @@ -0,0 +1,64 @@ +layer: + type: Board + description: Board setup for AI/ML with Ethos U85 + for-board: ARM::SSE-320 + for-device: ARM::SSE-320-FVP + + connections: + - connect: Corstone-320 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-320.h\" + - ETHOSU85 + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::ethos-u-core-driver@^1.25.2 + - pack: ARM::AVH_FVP + - pack: ARM::SSE_320_BSP@1.0.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + - component: Machine Learning:NPU Support:Ethos-U Driver&Generic U85 + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./ethos_setup.c + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-320.h diff --git a/board/Corstone-320/Board.clayer.yml b/board/Corstone-320/Board.clayer.yml new file mode 100644 index 0000000..f7b3e92 --- /dev/null +++ b/board/Corstone-320/Board.clayer.yml @@ -0,0 +1,59 @@ +layer: + type: Board + description: Board setup for AI/ML + for-board: ARM::SSE-320 + for-device: ARM::SSE-320-FVP + + connections: + - connect: Corstone-320 + provides: + - CMSIS_USART + - CMSIS_VSTREAM_AUDIO_IN + - CMSIS_VSTREAM_AUDIO_OUT + - CMSIS_VSTREAM_VIDEO_IN + - CMSIS_VSTREAM_VIDEO_OUT + - STDOUT + - STDERR + - Heap: 786432 + + define: + - CMSIS_target_header: \"Corstone-320.h\" + - ARM_MODEL_USE_PMU_COUNTERS + + packs: + - pack: ARM::CMSIS + - pack: ARM::CMSIS-Compiler@^2.1.0 + - pack: ARM::AVH_FVP + - pack: ARM::SSE_320_BSP@1.0.0 + + components: + - component: CMSIS:CORE + + - component: CMSIS Driver:USART + - component: CMSIS Driver:vStream:AudioIn + - component: CMSIS Driver:vStream:AudioOut + - component: CMSIS Driver:vStream:VideoIn + - component: CMSIS Driver:vStream:VideoOut + + - component: CMSIS-Compiler:CORE + - component: CMSIS-Compiler:STDERR:Custom + - component: CMSIS-Compiler:STDIN:Custom + - component: CMSIS-Compiler:STDOUT:Custom + + - component: Device:Definition + - component: Device:Startup&C Startup + + - component: Device:Native Driver:SysCounter + - component: Device:Native Driver:SysTimer + - component: Device:Native Driver:Timeout + - component: Device:Native Driver:UART + + groups: + - group: Board + files: + - file: ./main.c + - file: ./main.h + - file: ./retarget_stdio.c + + linker: + - regions: ./regions_SSE-320.h diff --git a/board/Corstone-320/Corstone-320.h b/board/Corstone-320/Corstone-320.h new file mode 100644 index 0000000..456d842 --- /dev/null +++ b/board/Corstone-320/Corstone-320.h @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef CORSTONE_320_H_ +#define CORSTONE_320_H_ + +#include "Driver_USART.h" +#include "cmsis_vstream.h" + +// CMSIS Driver instances of Board peripherals +#define CMSIS_DRIVER_USART 0 // CMSIS Driver USART instance number + +// Retarget stdio to CMSIS UART +#define RETARGET_STDIO_UART 0 + +// CMSIS Drivers +extern ARM_DRIVER_USART Driver_USART0; /* Serial */ +extern vStreamDriver_t Driver_vStreamAudioIn; /* Audio In Stream */ +extern vStreamDriver_t Driver_vStreamAudioOut; /* Audio Out Stream */ +extern vStreamDriver_t Driver_vStreamVideoIn; /* Video In Stream */ +extern vStreamDriver_t Driver_vStreamVideoOut; /* Video Out Stream */ + +#ifdef CMSIS_shield_header +#include CMSIS_shield_header +#endif + +#endif /* CORSTONE_320_H_ */ diff --git a/board/Corstone-320/README.md b/board/Corstone-320/README.md new file mode 100644 index 0000000..21f3c3b --- /dev/null +++ b/board/Corstone-320/README.md @@ -0,0 +1,35 @@ +# Board: Arm SSE-320 + +## Board Layer for Corstone-320 FVP + +Device: SSE-320-FVP + +### System Configuration + +| System Component | Setting +|:------------------------|:---------------------------------- +| Heap | 768 kB (configured in linker file) +| Stack (MSP) | 32 kB (configured in linker file) + +### STDIO mapping + +**STDIO** is routed to terminal via **UART0** peripheral + +### CMSIS-Driver mapping + +| CMSIS-Driver | Peripheral | Connection +|:-----------------------|:-----------|:---------------------- +| Driver_USART0 | UART0 | STDOUT, STDERR +| Driver_vStreamAudioIn | VSI0 | CMSIS_VSTREAM_AUDIO_IN +| Driver_vStreamAudioOut | VSI1 | CMSIS_VSTREAM_AUDIO_OUT +| Driver_vStreamVideoIn | VSI4 | CMSIS_VSTREAM_VIDEO_IN +| Driver_vStreamVideoOut | VSI6 | CMSIS_VSTREAM_VIDEO_OUT + +### CMSIS-Driver vStream configuration + +| Driver | Stream Format Description +|:-----------------------|:---------------------------------------------------- +| 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) diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 new file mode 100644 index 0000000..72953b0 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_in_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_IN_CONFIG_H_ +#define VSTREAM_AUDIO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_IN_CHANNELS +#define AUDIO_IN_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_IN_SAMPLE_BITS +#define AUDIO_IN_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_IN_SAMPLE_RATE +#define AUDIO_IN_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_IN_DEVICE +#define AUDIO_IN_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_IN_FILENAME +#define AUDIO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 new file mode 100644 index 0000000..a8b6859 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_audio_out_config.h.base@1.0.0 @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_AUDIO_OUT_CONFIG_H_ +#define VSTREAM_AUDIO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Number of channels <1=>Mono <2=>Stereo +// Defines the number of audio channels in stream. +// Default: 2 +#ifndef AUDIO_OUT_CHANNELS +#define AUDIO_OUT_CHANNELS 2 +#endif + +// Number of bits per sample <0=>8 <1=>16 <2=>24 <3=>32 +// Defines number of bits of information in each sample. +// Default: 16 +#ifndef AUDIO_OUT_SAMPLE_BITS +#define AUDIO_OUT_SAMPLE_BITS 16 +#endif + +// Sample rate <8000=>8 kHz <16000=>16 kHz <44100=>44.1 kHz <48000=>48 kHz +// Defines the number of samples captured per second. +// Default: 16000 +#ifndef AUDIO_OUT_SAMPLE_RATE +#define AUDIO_OUT_SAMPLE_RATE 16000 +#endif + +// Streaming Device Index +// Defines the system index of the audio streaming device. +// Default: -1 (system default audio device) +#ifndef AUDIO_OUT_DEVICE +#define AUDIO_OUT_DEVICE -1 +#endif + +// Audio File Name +// Defines the name of the audio file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef AUDIO_OUT_FILENAME +#define AUDIO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h new file mode 100644 index 0000000..fd1d7d0 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 new file mode 100644 index 0000000..a4e79fe --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_in_config.h.base@1.0.0 @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_IN_CONFIG_H_ +#define VSTREAM_VIDEO_IN_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_IN_FRAME_WIDTH +#define VIDEO_IN_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_IN_FRAME_HEIGHT +#define VIDEO_IN_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_IN_FRAME_RATE +#define VIDEO_IN_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_IN_FRAME_COLOR +#define VIDEO_IN_FRAME_COLOR 1 +#endif + +// Streaming Device Index +// Defines the system index of the video streaming device. +// Default: -1 (system default video device) +#ifndef VIDEO_IN_DEVICE +#define VIDEO_IN_DEVICE -1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_IN_FILENAME +#define VIDEO_IN_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h new file mode 100644 index 0000000..da9aa7e --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 640 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 480 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 new file mode 100644 index 0000000..b59bf69 --- /dev/null +++ b/board/Corstone-320/RTE/CMSIS_Driver/vstream_video_out_config.h.base@1.0.0 @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef VSTREAM_VIDEO_OUT_CONFIG_H_ +#define VSTREAM_VIDEO_OUT_CONFIG_H_ + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// Frame width +// Defines the video stream frame width in pixels. +// Common frame widths: 320, 640, 800, 1024. +// Default: 640 +#ifndef VIDEO_OUT_FRAME_WIDTH +#define VIDEO_OUT_FRAME_WIDTH 320 +#endif + +// Frame height +// Defines the video stream frame height in pixels. +// Common frame heights: 240, 480, 600, 768. +// Default: 480 +#ifndef VIDEO_OUT_FRAME_HEIGHT +#define VIDEO_OUT_FRAME_HEIGHT 240 +#endif + +// Frame rate +// Defines the video stream frame rate in frames per second. +// Common frame rates: 15, 25, 30, 60. +// Default: 30 +#ifndef VIDEO_OUT_FRAME_RATE +#define VIDEO_OUT_FRAME_RATE 30 +#endif + +// Color format <0=>Grayscale(8-bit) <1=>RGB888 <2=>BGR565 <3=>YUV420 <4=>NV12 <5=>NV21 +// Defines the video frame color space. +// Default: 1 +#ifndef VIDEO_OUT_FRAME_COLOR +#define VIDEO_OUT_FRAME_COLOR 1 +#endif + +// Video File Name +// Defines the name of the video file to be used for streaming. +// Default: "" (use streaming device instead of file) +#ifndef VIDEO_OUT_FILENAME +#define VIDEO_OUT_FILENAME "" +#endif + +#endif diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src b/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src new file mode 100644 index 0000000..233a6de --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/ac6_linker_script.sct.src @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE 8 +#else +#define __STACKSEAL_SIZE 0 +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + + ER_ROM0 __ROM0_BASE __ROM0_SIZE { + *.o (RESET, +First) + *(InRoot$$Sections) + } + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER AlignExpr(+0, 32) (__ROM0_SIZE - AlignExpr(ImageLength(ER_ROM0), 32)) { + *(Veneer$$CMSE) + } +#endif +} + +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + + ER_ROM1 __ROM1_BASE __ROM1_SIZE { + *(+RO +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE) { + *.o(.bss.noinit) + *.o(.bss.noinit.*) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - __STACKSEAL_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY __STACKSEAL_SIZE { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#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) + + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + ; NN Model Binary Representation + *.o (nn_model) + + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h b/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h new file mode 100644 index 0000000..19e2c88 --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif +#ifdef RTE_I2C1 +#define I2C1_SBCON_S +#define I2C1_SBCON_DEV I2C1_SBCON_DEV_S +#endif +#ifdef RTE_I2C2 +#define I2C2_SBCON_S +#define I2C2_SBCON_DEV I2C2_SBCON_DEV_S +#endif +#ifdef RTE_I2C3 +#define I2C3_SBCON_S +#define I2C3_SBCON_DEV I2C3_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif +#ifdef RTE_USART2 +#define UART2_CMSDK_S +#define UART2_CMSDK_DEV UART2_CMSDK_DEV_S +#endif +#ifdef RTE_USART3 +#define UART3_CMSDK_S +#define UART3_CMSDK_DEV UART3_CMSDK_DEV_S +#endif +#ifdef RTE_USART4 +#define UART4_CMSDK_S +#define UART4_CMSDK_DEV UART4_CMSDK_DEV_S +#endif +#ifdef RTE_USART5 +#define UART5_CMSDK_S +#define UART5_CMSDK_DEV UART5_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 320 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN0_S +#define PPC_CORSTONE320_MAIN0_DEV PPC_CORSTONE320_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP0_S +#define PPC_CORSTONE320_MAIN_EXP0_DEV PPC_CORSTONE320_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP1_S +#define PPC_CORSTONE320_MAIN_EXP1_DEV PPC_CORSTONE320_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP2_S +#define PPC_CORSTONE320_MAIN_EXP2_DEV PPC_CORSTONE320_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP3_S +#define PPC_CORSTONE320_MAIN_EXP3_DEV PPC_CORSTONE320_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH0_S +#define PPC_CORSTONE320_PERIPH0_DEV PPC_CORSTONE320_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH1_S +#define PPC_CORSTONE320_PERIPH1_DEV PPC_CORSTONE320_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP0_S +#define PPC_CORSTONE320_PERIPH_EXP0_DEV PPC_CORSTONE320_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP1_S +#define PPC_CORSTONE320_PERIPH_EXP1_DEV PPC_CORSTONE320_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP2_S +#define PPC_CORSTONE320_PERIPH_EXP2_DEV PPC_CORSTONE320_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP3_S +#define PPC_CORSTONE320_PERIPH_EXP3_DEV PPC_CORSTONE320_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* Key Management Unit */ +#ifdef RTE_KMU +#define KMU_S +#define KMU_DEV KMU_DEV_S +#endif + +/* Lifecycle Manager */ +#ifdef RTE_LCM +#define LCM_S +#define LCM_DEV LCM_DEV_S +#endif + +/* Security Alarm Manager */ +#ifdef RTE_SAM +#define SAM_S +#define SAM_DEV SAM_DEV_S +#endif + +/* HDLCD Video */ +#ifdef RTE_HDLCD +#define HDLCD_NS +#define HDLCD_DEV HDLCD_DEV_NS +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI0 +#define SPI0_PL022_S +#define SPI0_PL022_DEV SPI0_PL022_DEV_S +#endif +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif +#ifdef RTE_SPI2 +#define SPI2_PL022_S +#define SPI2_PL022_DEV SPI2_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h.base@1.1.0 b/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h.base@1.1.0 new file mode 100644 index 0000000..19e2c88 --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/device_cfg.h.base@1.1.0 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_CFG_H__ +#define __DEVICE_CFG_H__ + +#include "RTE_Components.h" + +/** + * \file device_cfg.h + * \brief Configuration file native driver re-targeting + * + * \details This file can be used to add native driver specific macro + * definitions to select which peripherals are available in the build. + * + * This is a default device configuration file with all peripherals enabled. + */ + +/* Secure only peripheral configuration */ + +/* ARM MPS3 IO SCC */ +#ifdef RTE_MPS3_IO +#define MPS3_IO_S +#define MPS3_IO_DEV MPS3_IO_DEV_S +#endif + +/* I2C_SBCon */ +#ifdef RTE_I2C0 +#define I2C0_SBCON_S +#define I2C0_SBCON_DEV I2C0_SBCON_DEV_S +#endif +#ifdef RTE_I2C1 +#define I2C1_SBCON_S +#define I2C1_SBCON_DEV I2C1_SBCON_DEV_S +#endif +#ifdef RTE_I2C2 +#define I2C2_SBCON_S +#define I2C2_SBCON_DEV I2C2_SBCON_DEV_S +#endif +#ifdef RTE_I2C3 +#define I2C3_SBCON_S +#define I2C3_SBCON_DEV I2C3_SBCON_DEV_S +#endif + +/* I2S */ +#ifdef RTE_I2S +#define MPS3_I2S_S +#define MPS3_I2S_DEV MPS3_I2S_DEV_S +#endif + +/* ARM UART Controller CMSDK */ +#ifdef RTE_USART0 +#define UART0_CMSDK_S +#define UART0_CMSDK_DEV UART0_CMSDK_DEV_S +#endif +#ifdef RTE_USART1 +#define UART1_CMSDK_S +#define UART1_CMSDK_DEV UART1_CMSDK_DEV_S +#endif +#ifdef RTE_USART2 +#define UART2_CMSDK_S +#define UART2_CMSDK_DEV UART2_CMSDK_DEV_S +#endif +#ifdef RTE_USART3 +#define UART3_CMSDK_S +#define UART3_CMSDK_DEV UART3_CMSDK_DEV_S +#endif +#ifdef RTE_USART4 +#define UART4_CMSDK_S +#define UART4_CMSDK_DEV UART4_CMSDK_DEV_S +#endif +#ifdef RTE_USART5 +#define UART5_CMSDK_S +#define UART5_CMSDK_DEV UART5_CMSDK_DEV_S +#endif + +#define DEFAULT_UART_BAUDRATE 115200U + +/* To be used as CODE and DATA sram */ +#ifdef RTE_ISRAM0_MPC +#define MPC_ISRAM0_S +#define MPC_ISRAM0_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_ISRAM1_MPC +#define MPC_ISRAM1_S +#define MPC_ISRAM1_DEV MPC_ISRAM0_DEV_S +#endif + +#ifdef RTE_SRAM_MPC +#define MPC_SRAM_S +#define MPC_SRAM_DEV MPC_SRAM_DEV_S +#endif + +#ifdef RTE_QSPI_MPC +#define MPC_QSPI_S +#define MPC_QSPI_DEV MPC_QSPI_DEV_S +#endif + +/** System Counter Armv8-M */ +#ifdef RTE_SYSCOUNTER +#define SYSCOUNTER_CNTRL_ARMV8_M_S +#define SYSCOUNTER_CNTRL_ARMV8_M_DEV SYSCOUNTER_CNTRL_ARMV8_M_DEV_S + +#define SYSCOUNTER_READ_ARMV8_M_S +#define SYSCOUNTER_READ_ARMV8_M_DEV SYSCOUNTER_READ_ARMV8_M_DEV_S +/** + * Arbitrary scaling values for test purposes + */ +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE0_FRACT 0u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_INT 1u +#define SYSCOUNTER_ARMV8_M_DEFAULT_SCALE1_FRACT 0u +#endif + +/* System timer */ +#ifdef RTE_TIMEOUT +#define SYSTIMER0_ARMV8_M_S +#define SYSTIMER0_ARMV8_M_DEV SYSTIMER0_ARMV8_M_DEV_S +#define SYSTIMER1_ARMV8_M_S +#define SYSTIMER1_ARMV8_M_DEV SYSTIMER1_ARMV8_M_DEV_S +#define SYSTIMER2_ARMV8_M_S +#define SYSTIMER2_ARMV8_M_DEV SYSTIMER2_ARMV8_M_DEV_S +#define SYSTIMER3_ARMV8_M_S +#define SYSTIMER3_ARMV8_M_DEV SYSTIMER3_ARMV8_M_DEV_S + +#define SYSTIMER0_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER1_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER2_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ (32000000ul) +#endif + +/* CMSDK GPIO driver structures */ +#ifdef RTE_GPIO +#define GPIO0_CMSDK_S +#define GPIO0_CMSDK_DEV GPIO0_CMSDK_DEV_S +#define GPIO1_CMSDK_S +#define GPIO1_CMSDK_DEV GPIO1_CMSDK_DEV_S +#define GPIO2_CMSDK_S +#define GPIO2_CMSDK_DEV GPIO2_CMSDK_DEV_S +#define GPIO3_CMSDK_S +#define GPIO3_CMSDK_DEV GPIO3_CMSDK_DEV_S +#endif + +/* System Watchdogs */ +#ifdef RTE_WATCHDOG +#define SYSWDOG_ARMV8_M_S +#define SYSWDOG_ARMV8_M_DEV SYSWDOG_ARMV8_M_DEV_S +#endif + +/* ARM MPC SIE 320 driver structures */ +#ifdef RTE_VM0_MPC +#define MPC_VM0_S +#define MPC_VM0_DEV MPC_VM0_DEV_S +#endif +#ifdef RTE_VM1_MPC +#define MPC_VM1_S +#define MPC_VM1_DEV MPC_VM1_DEV_S +#endif +#ifdef RTE_SSRAM2_MPC +#define MPC_SSRAM2_S +#define MPC_SSRAM2_DEV MPC_SSRAM2_DEV_S +#endif +#ifdef RTE_SSRAM3_MPC +#define MPC_SSRAM3_S +#define MPC_SSRAM3_DEV MPC_SSRAM3_DEV_S +#endif + +/* ARM PPC driver structures */ +#ifdef RTE_MAIN0_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN0_S +#define PPC_CORSTONE320_MAIN0_DEV PPC_CORSTONE320_MAIN0_DEV_S +#endif +#ifdef RTE_MAIN_EXP0_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP0_S +#define PPC_CORSTONE320_MAIN_EXP0_DEV PPC_CORSTONE320_MAIN_EXP0_DEV_S +#endif +#ifdef RTE_MAIN_EXP1_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP1_S +#define PPC_CORSTONE320_MAIN_EXP1_DEV PPC_CORSTONE320_MAIN_EXP1_DEV_S +#endif +#ifdef RTE_MAIN_EXP2_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP2_S +#define PPC_CORSTONE320_MAIN_EXP2_DEV PPC_CORSTONE320_MAIN_EXP2_DEV_S +#endif +#ifdef RTE_MAIN_EXP3_PPC_CORSTONE320 +#define PPC_CORSTONE320_MAIN_EXP3_S +#define PPC_CORSTONE320_MAIN_EXP3_DEV PPC_CORSTONE320_MAIN_EXP3_DEV_S +#endif +#ifdef RTE_PERIPH0_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH0_S +#define PPC_CORSTONE320_PERIPH0_DEV PPC_CORSTONE320_PERIPH0_DEV_S +#endif +#ifdef RTE_PERIPH1_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH1_S +#define PPC_CORSTONE320_PERIPH1_DEV PPC_CORSTONE320_PERIPH1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP0_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP0_S +#define PPC_CORSTONE320_PERIPH_EXP0_DEV PPC_CORSTONE320_PERIPH_EXP0_DEV_S +#endif +#ifdef RTE_PERIPH_EXP1_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP1_S +#define PPC_CORSTONE320_PERIPH_EXP1_DEV PPC_CORSTONE320_PERIPH_EXP1_DEV_S +#endif +#ifdef RTE_PERIPH_EXP2_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP2_S +#define PPC_CORSTONE320_PERIPH_EXP2_DEV PPC_CORSTONE320_PERIPH_EXP2_DEV_S +#endif +#ifdef RTE_PERIPH_EXP3_PPC_CORSTONE320 +#define PPC_CORSTONE320_PERIPH_EXP3_S +#define PPC_CORSTONE320_PERIPH_EXP3_DEV PPC_CORSTONE320_PERIPH_EXP3_DEV_S +#endif + +/* DMA350 */ +#ifdef RTE_DMA350 +#define DMA350_DMA0_S +#define DMA350_DMA0_DEV DMA350_DMA0_DEV_S + +#define DMA350_CH0_S +#define DMA350_DMA0_CH0_S +#define DMA350_CH1_S +#define DMA350_DMA0_CH1_S +#endif + +/* Key Management Unit */ +#ifdef RTE_KMU +#define KMU_S +#define KMU_DEV KMU_DEV_S +#endif + +/* Lifecycle Manager */ +#ifdef RTE_LCM +#define LCM_S +#define LCM_DEV LCM_DEV_S +#endif + +/* Security Alarm Manager */ +#ifdef RTE_SAM +#define SAM_S +#define SAM_DEV SAM_DEV_S +#endif + +/* HDLCD Video */ +#ifdef RTE_HDLCD +#define HDLCD_NS +#define HDLCD_DEV HDLCD_DEV_NS +#endif + +/* ARM SPI PL022 */ +/* Invalid device stubs are not defined */ +#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */ +#ifdef RTE_SPI0 +#define SPI0_PL022_S +#define SPI0_PL022_DEV SPI0_PL022_DEV_S +#endif +#ifdef RTE_SPI1 +#define SPI1_PL022_S +#define SPI1_PL022_DEV SPI1_PL022_DEV_S +#endif +#ifdef RTE_SPI2 +#define SPI2_PL022_S +#define SPI2_PL022_DEV SPI2_PL022_DEV_S +#endif + +#endif /* __DEVICE_CFG_H__ */ diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src b/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src new file mode 100644 index 0000000..2e2ef6f --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/gcc_linker_script.ld.src @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + 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) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __noinit_start + * __noinit_end + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .boot : + { + KEEP(*(.vectors)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .text : + { + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM1 + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM1 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM1 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + LONG (LOADADDR(.init_buf)) + LONG (ADDR(.init_buf)) + LONG (SIZEOF(.init_buf) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM1 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM1 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM1 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM1 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit (NOLOAD) : + { + . = ALIGN(4); + __noinit_start = .; + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + __noinit_end = .; + } > RAM0 + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + /* Non-initialized buffers in fast access RAM */ + .cache (NOLOAD): + { + . = ALIGN(32); + *(*ethos_cache_buf) /* Ethos-U Cache Area */ + *(*activation_buf) /* NN Activation Tensor (activation buffer / tensor arena) */ + } > RAM1 + + /* Initialized buffers in fast access RAM */ + /* Entry must exist in .copy.table */ + .init_buf : + { + /* Add objects that go into RAM1 */ + } > RAM1 AT > ROM1 + + .rom2 : + { + *(*nn_model) /* NN Model Binary Representation */ + } > ROM2 + + .rom3 : + { + /* Add objects that go into ROM3 */ + } > ROM3 +} diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src b/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src new file mode 100644 index 0000000..ea02d53 --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/iar_linker_script.icf.src @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +define memory mem with size = 4G; + +#if __ROM0_SIZE > 0 + define region ROM0_region = mem:[from __ROM0_BASE to (__ROM0_BASE+__ROM0_SIZE-1)]; +#else + define region ROM0_region = []; +#endif + +#if __ROM1_SIZE > 0 + define region ROM1_region = mem:[from __ROM1_BASE to (__ROM1_BASE+__ROM1_SIZE-1)]; +#else + define region ROM1_region = []; +#endif + +#if __ROM2_SIZE > 0 + define region ROM2_region = mem:[from __ROM2_BASE to (__ROM2_BASE+__ROM2_SIZE-1)]; +#else + define region ROM2_region = []; +#endif + +#if __ROM3_SIZE > 0 + define region ROM3_region = mem:[from __ROM3_BASE to (__ROM3_BASE+__ROM3_SIZE-1)]; +#else + 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 + define region RAM0_region = []; +#endif + +#if __RAM1_SIZE > 0 + define region RAM1_region = mem:[from __RAM1_BASE to (__RAM1_BASE+__RAM1_SIZE-1)]; +#else + define region RAM1_region = []; +#endif + +#if __RAM2_SIZE > 0 + define region RAM2_region = mem:[from __RAM2_BASE to (__RAM2_BASE+__RAM2_SIZE-1)]; +#else + define region RAM2_region = []; +#endif + +#if __RAM3_SIZE > 0 + define region RAM3_region = mem:[from __RAM3_BASE to (__RAM3_BASE+__RAM3_SIZE-1)]; +#else + 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)) +{ + // Required in a multi-threaded application + initialize by copy with packing = none { section __DLIB_PERTHREAD }; +} + +place at address mem:__ROM0_BASE { readonly section .intvec }; + +if (!isempty(ROM_region)) +{ + place in ROM_region { readonly }; +} + +if (!isempty(RAM_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 }; +} diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c b/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c new file mode 100644 index 0000000..2caeffa --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE320.h" +#include "system_SSE320.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +__NO_RETURN void __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(SDC_Handler) +DEFAULT_IRQ_HANDLER(KMU_Handler) +DEFAULT_IRQ_HANDLER(DMA_SEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_NONSEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_SECURITY_VIOLATION_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) +DEFAULT_IRQ_HANDLER(SAM_Critical_Severity_Fault_Handler) +DEFAULT_IRQ_HANDLER(SAM_Severity_Fault_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(RTC_Handler) +DEFAULT_IRQ_HANDLER(ISP_C55_Handler) +DEFAULT_IRQ_HANDLER(HDLCD_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + SDC_Handler, /* 15: Secure Debug Channel Handler */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + KMU_Handler, /* 20: KMU Handler */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + DMA_SEC_Combined_Handler, /* 24: DMA Secure Combined Handler */ + DMA_NONSEC_Combined_Handler, /* 25: DMA Non-Secure Combined Handler */ + DMA_SECURITY_VIOLATION_Handler, /* 26: DMA Security Violation Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + SAM_Critical_Severity_Fault_Handler, /* 30: SAM Critical Severity Fault Handler */ + SAM_Severity_Fault_Handler, /* 31: SAM Severity Fault Handler */ + + /* External interrupts */ + 0, /* 32: Reserved */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + 0, /* 51: Reserved */ + 0, /* 52: Reserved */ + 0, /* 53: Reserved */ + 0, /* 54: Reserved */ + 0, /* 55: Reserved */ + 0, /* 56: Reserved */ + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + 0, /* 73: Reserved */ + 0, /* 74: Reserved */ + 0, /* 75: Reserved */ + 0, /* 76: Reserved */ + 0, /* 77: Reserved */ + 0, /* 78: Reserved */ + 0, /* 79: Reserved */ + 0, /* 80: Reserved */ + 0, /* 81: Reserved */ + 0, /* 82: Reserved */ + 0, /* 83: Reserved */ + 0, /* 84: Reserved */ + 0, /* 85: Reserved */ + 0, /* 86: Reserved */ + 0, /* 87: Reserved */ + 0, /* 88: Reserved */ + 0, /* 89: Reserved */ + 0, /* 90: Reserved */ + 0, /* 91: Reserved */ + 0, /* 92: Reserved */ + 0, /* 93: Reserved */ + 0, /* 94: Reserved */ + 0, /* 95: Reserved */ + 0, /* 96: Reserved */ + 0, /* 97: Reserved */ + 0, /* 98: Reserved */ + 0, /* 99: Reserved */ + 0, /* 100: Reserved */ + 0, /* 101: Reserved */ + 0, /* 102: Reserved */ + 0, /* 103: Reserved */ + 0, /* 104: Reserved */ + 0, /* 105: Reserved */ + 0, /* 106: Reserved */ + 0, /* 107: Reserved */ + 0, /* 108: Reserved */ + 0, /* 109: Reserved */ + 0, /* 110: Reserved */ + 0, /* 111: Reserved */ + 0, /* 112: Reserved */ + 0, /* 113: Reserved */ + 0, /* 114: Reserved */ + 0, /* 115: Reserved */ + 0, /* 116: Reserved */ + 0, /* 117: Reserved */ + 0, /* 118: Reserved */ + 0, /* 119: Reserved */ + 0, /* 120: Reserved */ + 0, /* 121: Reserved */ + 0, /* 122: Reserved */ + 0, /* 123: Reserved */ + 0, /* 124: Reserved */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + 0, /* 127: Reserved */ + RTC_Handler, /* 128: UART 5 combined Interrupt */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + ISP_C55_Handler, /* 132: ISP C55 Handler */ + HDLCD_Handler, /* 133: HDLCD Handler */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c.base@1.1.0 b/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c.base@1.1.0 new file mode 100644 index 0000000..2caeffa --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/startup_SSE320.c.base@1.1.0 @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 startup_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE320.h" +#include "system_SSE320.h" + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint64_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler (void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +#define DEFAULT_IRQ_HANDLER(handler_name) \ +__NO_RETURN void __WEAK handler_name(void); \ +void handler_name(void) { \ + while(1); \ +} + +/* Exceptions */ +DEFAULT_IRQ_HANDLER(NMI_Handler) +DEFAULT_IRQ_HANDLER(HardFault_Handler) +DEFAULT_IRQ_HANDLER(MemManage_Handler) +DEFAULT_IRQ_HANDLER(BusFault_Handler) +DEFAULT_IRQ_HANDLER(UsageFault_Handler) +DEFAULT_IRQ_HANDLER(SecureFault_Handler) +DEFAULT_IRQ_HANDLER(SVC_Handler) +DEFAULT_IRQ_HANDLER(DebugMon_Handler) +DEFAULT_IRQ_HANDLER(PendSV_Handler) +DEFAULT_IRQ_HANDLER(SysTick_Handler) + +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_RESET_REQ_Handler) +DEFAULT_IRQ_HANDLER(NONSEC_WATCHDOG_Handler) +DEFAULT_IRQ_HANDLER(SLOWCLK_Timer_Handler) +DEFAULT_IRQ_HANDLER(TFM_TIMER0_IRQ_Handler) +DEFAULT_IRQ_HANDLER(TIMER1_Handler) +DEFAULT_IRQ_HANDLER(TIMER2_Handler) +DEFAULT_IRQ_HANDLER(MPC_Handler) +DEFAULT_IRQ_HANDLER(PPC_Handler) +DEFAULT_IRQ_HANDLER(MSC_Handler) +DEFAULT_IRQ_HANDLER(BRIDGE_ERROR_Handler) +DEFAULT_IRQ_HANDLER(COMBINED_PPU_Handler) +DEFAULT_IRQ_HANDLER(SDC_Handler) +DEFAULT_IRQ_HANDLER(KMU_Handler) +DEFAULT_IRQ_HANDLER(DMA_SEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_NONSEC_Combined_Handler) +DEFAULT_IRQ_HANDLER(DMA_SECURITY_VIOLATION_Handler) +DEFAULT_IRQ_HANDLER(TIMER3_AON_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_0_Handler) +DEFAULT_IRQ_HANDLER(CPU0_CTI_1_Handler) +DEFAULT_IRQ_HANDLER(SAM_Critical_Severity_Fault_Handler) +DEFAULT_IRQ_HANDLER(SAM_Severity_Fault_Handler) + +DEFAULT_IRQ_HANDLER(System_Timestamp_Counter_Handler) +DEFAULT_IRQ_HANDLER(UARTRX0_Handler) +DEFAULT_IRQ_HANDLER(UARTTX0_Handler) +DEFAULT_IRQ_HANDLER(UARTRX1_Handler) +DEFAULT_IRQ_HANDLER(UARTTX1_Handler) +DEFAULT_IRQ_HANDLER(UARTRX2_Handler) +DEFAULT_IRQ_HANDLER(UARTTX2_Handler) +DEFAULT_IRQ_HANDLER(UARTRX3_Handler) +DEFAULT_IRQ_HANDLER(UARTTX3_Handler) +DEFAULT_IRQ_HANDLER(UARTRX4_Handler) +DEFAULT_IRQ_HANDLER(UARTTX4_Handler) +DEFAULT_IRQ_HANDLER(UART0_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART1_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART2_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UART4_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTOVF_Handler) +DEFAULT_IRQ_HANDLER(ETHERNET_Handler) +DEFAULT_IRQ_HANDLER(I2S_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_0_Handler) +DEFAULT_IRQ_HANDLER(DMA_Channel_1_Handler) +DEFAULT_IRQ_HANDLER(NPU0_Handler) +DEFAULT_IRQ_HANDLER(GPIO0_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO1_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO2_Combined_Handler) +DEFAULT_IRQ_HANDLER(GPIO3_Combined_Handler) +DEFAULT_IRQ_HANDLER(UARTRX5_Handler) +DEFAULT_IRQ_HANDLER(UARTTX5_Handler) +DEFAULT_IRQ_HANDLER(RTC_Handler) +DEFAULT_IRQ_HANDLER(ISP_C55_Handler) +DEFAULT_IRQ_HANDLER(HDLCD_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI0_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI1_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI2_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI3_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI4_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI5_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI6_Handler) +DEFAULT_IRQ_HANDLER(ARM_VSI7_Handler) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; + const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14: NMI Handler */ + HardFault_Handler, /* -13: Hard Fault Handler */ + MemManage_Handler, /* -12: MPU Fault Handler */ + BusFault_Handler, /* -11: Bus Fault Handler */ + UsageFault_Handler, /* -10: Usage Fault Handler */ + SecureFault_Handler, /* -9: Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5: SVCall Handler */ + DebugMon_Handler, /* -4: Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2: PendSV Handler */ + SysTick_Handler, /* -1: SysTick Handler */ + + NONSEC_WATCHDOG_RESET_REQ_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */ + NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Handler */ + SLOWCLK_Timer_Handler, /* 2: SLOWCLK Timer Handler */ + TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */ + TIMER1_Handler, /* 4: TIMER 1 Handler */ + TIMER2_Handler, /* 5: TIMER 2 Handler */ + 0, /* 6: Reserved */ + 0, /* 7: Reserved */ + 0, /* 8: Reserved */ + MPC_Handler, /* 9: MPC Combined (Secure) Handler */ + PPC_Handler, /* 10: PPC Combined (Secure) Handler */ + MSC_Handler, /* 11: MSC Combined (Secure) Handler */ + BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */ + 0, /* 13: Reserved */ + COMBINED_PPU_Handler, /* 14: Combined PPU Handler */ + SDC_Handler, /* 15: Secure Debug Channel Handler */ + NPU0_Handler, /* 16: NPU0 Handler */ + 0, /* 17: Reserved */ + 0, /* 18: Reserved */ + 0, /* 19: Reserved */ + KMU_Handler, /* 20: KMU Handler */ + 0, /* 21: Reserved */ + 0, /* 22: Reserved */ + 0, /* 23: Reserved */ + DMA_SEC_Combined_Handler, /* 24: DMA Secure Combined Handler */ + DMA_NONSEC_Combined_Handler, /* 25: DMA Non-Secure Combined Handler */ + DMA_SECURITY_VIOLATION_Handler, /* 26: DMA Security Violation Handler */ + TIMER3_AON_Handler, /* 27: TIMER 3 AON Handler */ + CPU0_CTI_0_Handler, /* 28: CPU0 CTI IRQ 0 Handler */ + CPU0_CTI_1_Handler, /* 29: CPU0 CTI IRQ 1 Handler */ + SAM_Critical_Severity_Fault_Handler, /* 30: SAM Critical Severity Fault Handler */ + SAM_Severity_Fault_Handler, /* 31: SAM Severity Fault Handler */ + + /* External interrupts */ + 0, /* 32: Reserved */ + UARTRX0_Handler, /* 33: UART 0 RX Handler */ + UARTTX0_Handler, /* 34: UART 0 TX Handler */ + UARTRX1_Handler, /* 35: UART 1 RX Handler */ + UARTTX1_Handler, /* 36: UART 1 TX Handler */ + UARTRX2_Handler, /* 37: UART 2 RX Handler */ + UARTTX2_Handler, /* 38: UART 2 TX Handler */ + UARTRX3_Handler, /* 39: UART 3 RX Handler */ + UARTTX3_Handler, /* 40: UART 3 TX Handler */ + UARTRX4_Handler, /* 41: UART 4 RX Handler */ + UARTTX4_Handler, /* 42: UART 4 TX Handler */ + UART0_Combined_Handler, /* 43: UART 0 Combined Handler */ + UART1_Combined_Handler, /* 44: UART 1 Combined Handler */ + UART2_Combined_Handler, /* 45: UART 2 Combined Handler */ + UART3_Combined_Handler, /* 46: UART 3 Combined Handler */ + UART4_Combined_Handler, /* 47: UART 4 Combined Handler */ + UARTOVF_Handler, /* 48: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */ + ETHERNET_Handler, /* 49: Ethernet Handler */ + I2S_Handler, /* 50: Audio I2S Handler */ + 0, /* 51: Reserved */ + 0, /* 52: Reserved */ + 0, /* 53: Reserved */ + 0, /* 54: Reserved */ + 0, /* 55: Reserved */ + 0, /* 56: Reserved */ + DMA_Channel_0_Handler, /* 57: DMA (DMA350) Channel 0 Handler */ + DMA_Channel_1_Handler, /* 58: DMA (DMA350) Channel 1 Handler */ + 0, /* 59: Reserved */ + 0, /* 60: Reserved */ + 0, /* 61: Reserved */ + 0, /* 62: Reserved */ + 0, /* 63: Reserved */ + 0, /* 64: Reserved */ + 0, /* 65: Reserved */ + 0, /* 66: Reserved */ + 0, /* 67: Reserved */ + 0, /* 68: Reserved */ + GPIO0_Combined_Handler, /* 69: GPIO 0 Combined Handler */ + GPIO1_Combined_Handler, /* 70: GPIO 1 Combined Handler */ + GPIO2_Combined_Handler, /* 71: GPIO 2 Combined Handler */ + GPIO3_Combined_Handler, /* 72: GPIO 3 Combined Handler */ + 0, /* 73: Reserved */ + 0, /* 74: Reserved */ + 0, /* 75: Reserved */ + 0, /* 76: Reserved */ + 0, /* 77: Reserved */ + 0, /* 78: Reserved */ + 0, /* 79: Reserved */ + 0, /* 80: Reserved */ + 0, /* 81: Reserved */ + 0, /* 82: Reserved */ + 0, /* 83: Reserved */ + 0, /* 84: Reserved */ + 0, /* 85: Reserved */ + 0, /* 86: Reserved */ + 0, /* 87: Reserved */ + 0, /* 88: Reserved */ + 0, /* 89: Reserved */ + 0, /* 90: Reserved */ + 0, /* 91: Reserved */ + 0, /* 92: Reserved */ + 0, /* 93: Reserved */ + 0, /* 94: Reserved */ + 0, /* 95: Reserved */ + 0, /* 96: Reserved */ + 0, /* 97: Reserved */ + 0, /* 98: Reserved */ + 0, /* 99: Reserved */ + 0, /* 100: Reserved */ + 0, /* 101: Reserved */ + 0, /* 102: Reserved */ + 0, /* 103: Reserved */ + 0, /* 104: Reserved */ + 0, /* 105: Reserved */ + 0, /* 106: Reserved */ + 0, /* 107: Reserved */ + 0, /* 108: Reserved */ + 0, /* 109: Reserved */ + 0, /* 110: Reserved */ + 0, /* 111: Reserved */ + 0, /* 112: Reserved */ + 0, /* 113: Reserved */ + 0, /* 114: Reserved */ + 0, /* 115: Reserved */ + 0, /* 116: Reserved */ + 0, /* 117: Reserved */ + 0, /* 118: Reserved */ + 0, /* 119: Reserved */ + 0, /* 120: Reserved */ + 0, /* 121: Reserved */ + 0, /* 122: Reserved */ + 0, /* 123: Reserved */ + 0, /* 124: Reserved */ + UARTRX5_Handler, /* 125: UART 5 RX Interrupt */ + UARTTX5_Handler, /* 126: UART 5 TX Interrupt */ + 0, /* 127: Reserved */ + RTC_Handler, /* 128: UART 5 combined Interrupt */ + 0, /* 129: Reserved */ + 0, /* 130: Reserved */ + 0, /* 131: Reserved */ + ISP_C55_Handler, /* 132: ISP C55 Handler */ + HDLCD_Handler, /* 133: HDLCD Handler */ + 0, /* 134: Reserved */ + 0, /* 135: Reserved */ + 0, /* 136: Reserved */ + 0, /* 137: Reserved */ + 0, /* 138: Reserved */ + 0, /* 139: Reserved */ + 0, /* 140: Reserved */ + 0, /* 141: Reserved */ + 0, /* 142: Reserved */ + 0, /* 143: Reserved */ + 0, /* 144: Reserved */ + 0, /* 145: Reserved */ + 0, /* 146: Reserved */ + 0, /* 147: Reserved */ + 0, /* 148: Reserved */ + 0, /* 149: Reserved */ + 0, /* 150: Reserved */ + 0, /* 151: Reserved */ + 0, /* 152: Reserved */ + 0, /* 153: Reserved */ + 0, /* 154: Reserved */ + 0, /* 155: Reserved */ + 0, /* 156: Reserved */ + 0, /* 157: Reserved */ + 0, /* 158: Reserved */ + 0, /* 159: Reserved */ + 0, /* 160: Reserved */ + 0, /* 161: Reserved */ + 0, /* 162: Reserved */ + 0, /* 163: Reserved */ + 0, /* 164: Reserved */ + 0, /* 165: Reserved */ + 0, /* 166: Reserved */ + 0, /* 167: Reserved */ + 0, /* 168: Reserved */ + 0, /* 169: Reserved */ + 0, /* 170: Reserved */ + 0, /* 171: Reserved */ + 0, /* 172: Reserved */ + 0, /* 173: Reserved */ + 0, /* 174: Reserved */ + 0, /* 175: Reserved */ + 0, /* 176: Reserved */ + 0, /* 177: Reserved */ + 0, /* 178: Reserved */ + 0, /* 179: Reserved */ + 0, /* 180: Reserved */ + 0, /* 181: Reserved */ + 0, /* 182: Reserved */ + 0, /* 183: Reserved */ + 0, /* 184: Reserved */ + 0, /* 185: Reserved */ + 0, /* 186: Reserved */ + 0, /* 187: Reserved */ + 0, /* 188: Reserved */ + 0, /* 189: Reserved */ + 0, /* 190: Reserved */ + 0, /* 191: Reserved */ + 0, /* 192: Reserved */ + 0, /* 193: Reserved */ + 0, /* 194: Reserved */ + 0, /* 195: Reserved */ + 0, /* 196: Reserved */ + 0, /* 197: Reserved */ + 0, /* 198: Reserved */ + 0, /* 199: Reserved */ + 0, /* 200: Reserved */ + 0, /* 201: Reserved */ + 0, /* 202: Reserved */ + 0, /* 203: Reserved */ + 0, /* 204: Reserved */ + 0, /* 205: Reserved */ + 0, /* 206: Reserved */ + 0, /* 207: Reserved */ + 0, /* 208: Reserved */ + 0, /* 209: Reserved */ + 0, /* 210: Reserved */ + 0, /* 211: Reserved */ + 0, /* 212: Reserved */ + 0, /* 213: Reserved */ + 0, /* 214: Reserved */ + 0, /* 215: Reserved */ + 0, /* 216: Reserved */ + 0, /* 217: Reserved */ + 0, /* 218: Reserved */ + 0, /* 219: Reserved */ + 0, /* 220: Reserved */ + 0, /* 221: Reserved */ + 0, /* 222: Reserved */ + 0, /* 223: Reserved */ + ARM_VSI0_Handler, /* 224: VSI 0 Handler */ + ARM_VSI1_Handler, /* 225: VSI 1 Handler */ + ARM_VSI2_Handler, /* 226: VSI 2 Handler */ + ARM_VSI3_Handler, /* 227: VSI 3 Handler */ + ARM_VSI4_Handler, /* 228: VSI 4 Handler */ + ARM_VSI5_Handler, /* 229: VSI 5 Handler */ + ARM_VSI6_Handler, /* 230: VSI 6 Handler */ + ARM_VSI7_Handler, /* 231: VSI 7 Handler */ +}; + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM((uint32_t)(&__STACK_LIMIT)); + __set_PSPLIM((uint32_t)(&__STACK_LIMIT)); + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c b/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c new file mode 100644 index 0000000..9bb9a28 --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2024, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE320.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c.base@1.1.0 b/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c.base@1.1.0 new file mode 100644 index 0000000..9bb9a28 --- /dev/null +++ b/board/Corstone-320/RTE/Device/SSE-320-FVP/system_SSE320.c.base@1.1.0 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2009-2024, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file is derivative of CMSIS V5.9.0 system_ARMCM85.c + * Git SHA: 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c + */ + +#include "SSE320.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ + #define XTAL (25000000UL) + #define SYSTEM_CLOCK (XTAL) + #define PERIPHERAL_CLOCK (25000000UL) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; +uint32_t PeripheralClock = PERIPHERAL_CLOCK; + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* Set CPDLPSTATE.RLPSTATE to 0 + Set CPDLPSTATE.ELPSTATE to 0, to stop the processor from trying to switch the EPU into retention state. + Set CPDLPSTATE.CLPSTATE to 0, so PDCORE will not enter low-power state. */ + PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_RLPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk | + PWRMODCTL_CPDLPSTATE_CLPSTATE_Msk ); + +#if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ + (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) + SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */ + (3U << 11U*2U) ); /* enable CP11 Full Access */ + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; +#endif + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + + /* Enable Branch Prediction */ + SCB->CCR |= SCB_CCR_BP_Msk; + + __DSB(); + __ISB(); + + /* Disable cache, because of BL2->Secure change. + If cache is enabled, then code decompression can fail or cause uncertain + behaviour after switching to main. + If cache needed to be Enabled before decompression, make sure to Clean + and Invalidate it at the begining of main(..)! + + If so, use: + SCB_InvalidateICache(); // I cache cannot be cleaned + SCB_CleanInvalidateDCache(); + */ + SCB_DisableICache(); + SCB_DisableDCache(); + + SystemCoreClock = SYSTEM_CLOCK; + PeripheralClock = PERIPHERAL_CLOCK; +} diff --git a/board/Corstone-320/ethos_setup.c b/board/Corstone-320/ethos_setup.c new file mode 100644 index 0000000..ca26dfa --- /dev/null +++ b/board/Corstone-320/ethos_setup.c @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + + #include + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "ethosu_driver.h" +#include "main.h" + +#if defined(ETHOSU65) || defined(ETHOSU85) +/* Define Ethos-U NPU cache buffer size */ +#ifndef ETHOS_CACHE_BUF_SIZE +#define ETHOS_CACHE_BUF_SIZE 393216 +#endif + +/* Define Ethos-U cache buffer alignment */ +#ifndef ETHOS_CACHE_BUF_ALIGNMENT +#define ETHOS_CACHE_BUF_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))) +#endif +#endif + +/* Define Ethos-U NPU security mode */ +#ifndef ETHOS_SECURE_ENABLE +#define ETHOS_SECURE_ENABLE 1 +#endif + +/* Define Ethos-U NPU privilege mode */ +#ifndef ETHOS_PRIVILEGE_ENABLE +#define ETHOS_PRIVILEGE_ENABLE 1 +#endif + +/* 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; +#endif + +/* + Ethos NPU interrupt handler. +*/ +void NPU0_Handler(void) { + ethosu_irq_handler(&EthosDriver); +} + +/* + Initialize the Ethos NPU driver. +*/ +void ethos_setup (void) { + void * const ethos_base_addr = (void *)NPU0_APB_BASE_S; + struct ethosu_hw_info hw_info; + int rval; + + /* 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 */ + #else + 0, /* Cache memory pointer */ + 0, /* Cache memory size */ + #endif + ETHOS_SECURE_ENABLE, /* Secure enable */ + ETHOS_PRIVILEGE_ENABLE); /* Privileged mode */ + if (rval != 0) { + printf("Failed to initialize Arm Ethos-U driver\n"); + } + else { + NVIC_EnableIRQ(NPU0_IRQn); + + ethosu_get_hw_info(&EthosDriver, &hw_info); + + printf("Ethos-U version info:\n"); + printf("\tArch: v%u.%u.%u\n", hw_info.version.arch_major_rev, + hw_info.version.arch_minor_rev, + hw_info.version.arch_patch_rev); + printf("\tMACs/cc: %u\n", (uint32_t)(1 << hw_info.cfg.macs_per_cc)); + printf("\tCmd stream: v%u\n", hw_info.cfg.cmd_stream_version); + } +} diff --git a/board/Corstone-320/fvp_config.txt b/board/Corstone-320/fvp_config.txt new file mode 100644 index 0000000..027f82c --- /dev/null +++ b/board/Corstone-320/fvp_config.txt @@ -0,0 +1,8 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#------------------------------------------------------------------------------ +mps4_board.subsystem.ethosu.num_macs=1024 # (int , init-time) default = '0x400' : Number of 8x8 MACs performed per cycle (128, 256, 512, 1024, or 2048). : [0x80:0x800] +mps4_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) +mps4_board.visualisation.disable-visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +vis_hdlcd.disable_visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +#------------------------------------------------------------------------------ diff --git a/board/Corstone-320/main.c b/board/Corstone-320/main.c new file mode 100644 index 0000000..69b3485 --- /dev/null +++ b/board/Corstone-320/main.c @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2024 Arm Limited (or its affiliates). All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#include "RTE_Components.h" +#include CMSIS_device_header + +#include "main.h" + +int main (void) { + + /* Initialize STDIO */ + stdio_init(); + + #if defined(ETHOSU_ARCH) + /* Initialize Ethos NPU */ + ethos_setup(); + #endif + + return (app_main()); +} diff --git a/board/Corstone-320/main.h b/board/Corstone-320/main.h new file mode 100644 index 0000000..6e2048e --- /dev/null +++ b/board/Corstone-320/main.h @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2020-2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef MAIN_H__ +#define MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Prototypes */ +extern int app_main (void); +extern int stdio_init (void); + +#if defined(ETHOSU_ARCH) +extern void ethos_setup (void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/board/Corstone-320/regions_SSE-320.h b/board/Corstone-320/regions_SSE-320.h new file mode 100644 index 0000000..80eb41d --- /dev/null +++ b/board/Corstone-320/regions_SSE-320.h @@ -0,0 +1,115 @@ +#ifndef REGIONS_SSE_320_H +#define REGIONS_SSE_320_H + +#include "sse320_memmap_s.h" +#include "sse320_memmap_ns.h" + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- +//------ With VS Code: Open Preview for Configuration Wizard ------------------- + +// ROM Configuration +// ======================= +// __ROM0 +// Base address +// Defines base address of memory region. +// Contains Startup and Vector Table +// Default: BOOT_ROM_S_BASE +#define __ROM0_BASE BOOT_ROM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: BOOT_ROM_S_SIZE +#define __ROM0_SIZE BOOT_ROM_S_SIZE +// + +// __ROM1 +// Base address +// Defines base address of memory region. +// Default: FPGA_SRAM_S_BASE +#define __ROM1_BASE FPGA_SRAM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: FPGA_SRAM_S_SIZE +#define __ROM1_SIZE FPGA_SRAM_S_SIZE +// + +// __ROM2 +// Base address +// Defines base address of memory region. +// Default: DDR4_3_S_BASE +#define __ROM2_BASE DDR4_3_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_3_S_SIZE +#define __ROM2_SIZE DDR4_3_S_SIZE +// + +// __ROM3 +// Base address +// Defines base address of memory region. +// Default: QSPI_FLASH_S_BASE +#define __ROM3_BASE QSPI_FLASH_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: QSPI_FLASH_S_SIZE +#define __ROM3_SIZE QSPI_FLASH_S_SIZE +// + +// + +// RAM Configuration +// ======================= +// __RAM0 +// Base address +// Defines base address of memory region. +// Default: DDR4_1_S_BASE +#define __RAM0_BASE DDR4_1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DDR4_1_S_SIZE +#define __RAM0_SIZE DDR4_1_S_SIZE +// + +// __RAM1 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM0_S_BASE +#define __RAM1_BASE SRAM_VM0_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM0_S_SIZE +#define __RAM1_SIZE SRAM_VM0_S_SIZE +// + +// __RAM2 +// Base address +// Defines base address of memory region. +// Default: SRAM_VM1_S_BASE +#define __RAM2_BASE SRAM_VM1_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: SRAM_VM1_S_SIZE +#define __RAM2_SIZE SRAM_VM1_S_SIZE +// + +// __RAM3 +// Base address +// Defines base address of memory region. +// Default: DTCM_S_BASE +#define __RAM3_BASE DTCM_S_BASE +// Region size [bytes] +// Defines size of memory region. +// Default: DTCM_S_SIZE +#define __RAM3_SIZE DTCM_S_SIZE +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00001000 +#define __HEAP_SIZE 0x00018000 +// + +#endif /* REGIONS_SSE_320_H */ diff --git a/board/Corstone-320/retarget_stdio.c b/board/Corstone-320/retarget_stdio.c new file mode 100644 index 0000000..f553eed --- /dev/null +++ b/board/Corstone-320/retarget_stdio.c @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Name: retarget_stdio.c + * Purpose: Retarget stdio to CMSIS UART + * + *---------------------------------------------------------------------------*/ + +#ifdef CMSIS_target_header +#include CMSIS_target_header +#else +#include "Driver_USART.h" +#endif + +#ifndef RETARGET_STDIO_UART +#error "RETARGET_STDIO_UART not defined!" +#endif + +/* Compile-time configuration */ +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif + +/* References to the external retarget functions */ +extern int stdio_init (void); +extern int stderr_putchar (int ch); +extern int stdout_putchar (int ch); +extern int stdin_getchar (void); + +/* Reference to the underlying USART driver */ +#ifndef CMSIS_target_header +extern ARM_DRIVER_USART ARM_Driver_USART_(RETARGET_STDIO_UART); +#endif +#define ptrUSART (&ARM_Driver_USART_(RETARGET_STDIO_UART)) + +/** + Initialize stdio + + \return 0 on success, or -1 on error. +*/ +int stdio_init (void) { + + if (ptrUSART->Initialize(NULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | + ARM_USART_DATA_BITS_8 | + ARM_USART_PARITY_NONE | + ARM_USART_STOP_BITS_1 | + ARM_USART_FLOW_CONTROL_NONE, + UART_BAUDRATE) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_RX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + if (ptrUSART->Control(ARM_USART_CONTROL_TX, 1U) != ARM_DRIVER_OK) { + return -1; + } + + return 0; +} + +/** + Put a character to the stderr + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stderr_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Put a character to the stdout + + \param[in] ch Character to output + \return The character written, or -1 on write error. +*/ +int stdout_putchar (int ch) { + uint8_t buf[1]; + + if (ch == '\n') { + buf[0] = (uint8_t)'\r'; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + } + + buf[0] = (uint8_t)ch; + + if (ptrUSART->Send(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().tx_busy != 0U); + + return ch; +} + +/** + Get a character from the stdio + + \return The next character from the input, or -1 on read error. +*/ +int stdin_getchar (void) { + uint8_t buf[1]; + + if (ptrUSART->Receive(buf, 1U) != ARM_DRIVER_OK) { + return -1; + } + + while (ptrUSART->GetStatus().rx_busy != 0U); + + return (int)buf[0]; +} \ No newline at end of file diff --git a/board/Corstone-320/sse320_memmap_ns.h b/board/Corstone-320/sse320_memmap_ns.h new file mode 100644 index 0000000..354f78b --- /dev/null +++ b/board/Corstone-320/sse320_memmap_ns.h @@ -0,0 +1,102 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE320_MEMMAP_NS_H +#define SSE320_MEMMAP_NS_H + +/*============================================================================*/ +/* NON-SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Non-Secure */ +#define ITCM_NS_BASE 0x00000000 +#define ITCM_NS_SIZE 0x00008000 /* 32KB */ +#define ITCM_NS_LIMIT (ITCM_NS_BASE + ITCM_NS_SIZE - 1) + +/* FPGA SRAM - Non-Secure */ +#define FPGA_SRAM_NS_BASE 0x01000000 +#define FPGA_SRAM_NS_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_NS_LIMIT (FPGA_SRAM_NS_BASE + FPGA_SRAM_NS_SIZE - 1) + +/* DMA ITCM - Non-Secure */ +#define DMA_ITCM_NS_BASE 0x0A000000 +#define DMA_ITCM_NS_SIZE 0x00008000 /* 32KB */ +#define DMA_ITCM_NS_LIMIT (DMA_ITCM_NS_BASE + DMA_ITCM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Non-Secure */ +#define DTCM_NS_BASE 0x20000000 +#define DTCM_NS_SIZE 0x00008000 /* 32KB */ +#define DTCM_NS_LIMIT (DTCM_NS_BASE + DTCM_NS_SIZE - 1) + +/* SRAM VM0 - Non-Secure */ +#define SRAM_VM0_NS_BASE 0x21000000 +#define SRAM_VM0_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_NS_LIMIT (SRAM_VM0_NS_BASE + SRAM_VM0_NS_SIZE - 1) + +/* SRAM VM1 - Non-Secure */ +#define SRAM_VM1_NS_BASE 0x21200000 +#define SRAM_VM1_NS_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_NS_LIMIT (SRAM_VM1_NS_BASE + SRAM_VM1_NS_SIZE - 1) + +/* DMA DTCM - Non-Secure */ +#define DMA_DTCM_NS_BASE 0x24000000 +#define DMA_DTCM_NS_SIZE 0x00008000 /* 32KB */ +#define DMA_DTCM_NS_LIMIT (DMA_DTCM_NS_BASE + DMA_DTCM_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Non-Secure */ +#define QSPI_FLASH_NS_BASE 0x28000000 +#define QSPI_FLASH_NS_SIZE 0x08000000 /* 128MB */ +#define QSPI_FLASH_NS_LIMIT (QSPI_FLASH_NS_BASE + QSPI_FLASH_NS_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Non-Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 0 - Non-Secure */ +#define DDR4_0_NS_BASE 0x60000000 +#define DDR4_0_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_0_NS_LIMIT (DDR4_0_NS_BASE + DDR4_0_NS_SIZE - 1) + +/* DDR4 Region 2 - Non-Secure */ +#define DDR4_2_NS_BASE 0x80000000 +#define DDR4_2_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_2_NS_LIMIT (DDR4_2_NS_BASE + DDR4_2_NS_SIZE - 1) + +/* DDR4 Region 4 - Non-Secure */ +#define DDR4_4_NS_BASE 0xA0000000 +#define DDR4_4_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_4_NS_LIMIT (DDR4_4_NS_BASE + DDR4_4_NS_SIZE - 1) + +/* DDR4 Region 6 - Non-Secure */ +#define DDR4_6_NS_BASE 0xC0000000 +#define DDR4_6_NS_SIZE 0x10000000 /* 256MB */ +#define DDR4_6_NS_LIMIT (DDR4_6_NS_BASE + DDR4_6_NS_SIZE - 1) + +#endif /* SSE320_MEMMAP_NS_H */ diff --git a/board/Corstone-320/sse320_memmap_s.h b/board/Corstone-320/sse320_memmap_s.h new file mode 100644 index 0000000..42d7691 --- /dev/null +++ b/board/Corstone-320/sse320_memmap_s.h @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2025 Arm Limited (or its affiliates). + * All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------*/ + +#ifndef SSE320_MEMMAP_S_H +#define SSE320_MEMMAP_S_H + +/*============================================================================*/ +/* SECURE MEMORY REGIONS */ +/*============================================================================*/ + +/*---------------------------------------------------------------------------*/ +/* Secure Code Regions */ +/*---------------------------------------------------------------------------*/ + +/* ITCM - Secure */ +#define ITCM_S_BASE 0x10000000 +#define ITCM_S_SIZE 0x00008000 /* 32KB */ +#define ITCM_S_LIMIT (ITCM_S_BASE + ITCM_S_SIZE - 1) + +/* Boot ROM - Secure (Startup) */ +#define BOOT_ROM_S_BASE 0x11000000 +#define BOOT_ROM_S_SIZE 0x00020000 /* 128KB */ +#define BOOT_ROM_S_LIMIT (BOOT_ROM_S_BASE + BOOT_ROM_S_SIZE - 1) + +/* FPGA SRAM - Secure */ +#define FPGA_SRAM_S_BASE 0x12000000 +#define FPGA_SRAM_S_SIZE 0x00200000 /* 2MB */ +#define FPGA_SRAM_S_LIMIT (FPGA_SRAM_S_BASE + FPGA_SRAM_S_SIZE - 1) + +/* DMA ITCM - Secure */ +#define DMA_ITCM_S_BASE 0x1A000000 +#define DMA_ITCM_S_SIZE 0x00008000 /* 32KB */ +#define DMA_ITCM_S_LIMIT (DMA_ITCM_S_BASE + DMA_ITCM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure SRAM Regions */ +/*---------------------------------------------------------------------------*/ + +/* DTCM - Secure */ +#define DTCM_S_BASE 0x30000000 +#define DTCM_S_SIZE 0x00008000 /* 32KB */ +#define DTCM_S_LIMIT (DTCM_S_BASE + DTCM_S_SIZE - 1) + +/* SRAM VM0 - Secure */ +#define SRAM_VM0_S_BASE 0x31000000 +#define SRAM_VM0_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM0_S_LIMIT (SRAM_VM0_S_BASE + SRAM_VM0_S_SIZE - 1) + +/* SRAM VM1 - Secure */ +#define SRAM_VM1_S_BASE 0x31200000 +#define SRAM_VM1_S_SIZE 0x00200000 /* 2MB */ +#define SRAM_VM1_S_LIMIT (SRAM_VM1_S_BASE + SRAM_VM1_S_SIZE - 1) + +/* DMA DTCM - Secure */ +#define DMA_DTCM_S_BASE 0x34000000 +#define DMA_DTCM_S_SIZE 0x00008000 /* 32KB */ +#define DMA_DTCM_S_LIMIT (DMA_DTCM_S_BASE + DMA_DTCM_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure QSPI Flash Regions */ +/*---------------------------------------------------------------------------*/ + +/* QSPI Flash - Secure */ +#define QSPI_FLASH_S_BASE 0x38000000 +#define QSPI_FLASH_S_SIZE 0x08000000 /* 128MB */ +#define QSPI_FLASH_S_LIMIT (QSPI_FLASH_S_BASE + QSPI_FLASH_S_SIZE - 1) + +/*---------------------------------------------------------------------------*/ +/* Secure DDR4 Regions */ +/*---------------------------------------------------------------------------*/ + +/* DDR4 Region 1 - Secure */ +#define DDR4_1_S_BASE 0x70000000 +#define DDR4_1_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_1_S_LIMIT (DDR4_1_S_BASE + DDR4_1_S_SIZE - 1) + +/* DDR4 Region 3 - Secure */ +#define DDR4_3_S_BASE 0x90000000 +#define DDR4_3_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_3_S_LIMIT (DDR4_3_S_BASE + DDR4_3_S_SIZE - 1) + +/* DDR4 Region 5 - Secure */ +#define DDR4_5_S_BASE 0xB0000000 +#define DDR4_5_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_5_S_LIMIT (DDR4_5_S_BASE + DDR4_5_S_SIZE - 1) + +/* DDR4 Region 7 - Secure */ +#define DDR4_7_S_BASE 0xD0000000 +#define DDR4_7_S_SIZE 0x10000000 /* 256MB */ +#define DDR4_7_S_LIMIT (DDR4_7_S_BASE + DDR4_7_S_SIZE - 1) + +#endif /* SSE320_MEMMAP_S_H */ diff --git a/board/Corstone-320/vsi/python/arm_vsi0.py b/board/Corstone-320/vsi/python/arm_vsi0.py new file mode 100644 index 0000000..e1a7bfc --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi0.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 0 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi0_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6000) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/arm_vsi1.py b/board/Corstone-320/vsi/python/arm_vsi1.py new file mode 100644 index 0000000..f1271b5 --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi1.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 1 Python script + +##@addtogroup arm_vsi_py_vstream_audio +# @{ +# +##@package arm_vsi1_vstream_audio +#Documentation for VSI vStream Audio module. +# +#More details. + +import logging +import vsi_audio + +logger = logging.getLogger(__name__) +vsi_audio.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Audio Server configuration +server_address = ('127.0.0.1', 6001) +server_authkey = 'vsi_audio' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_audio.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_audio.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_audio.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_audio.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_audio.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_audio.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/arm_vsi4.py b/board/Corstone-320/vsi/python/arm_vsi4.py new file mode 100644 index 0000000..e15edf8 --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi4.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 4 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi4_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6004) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/arm_vsi5.py b/board/Corstone-320/vsi/python/arm_vsi5.py new file mode 100644 index 0000000..631f74d --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi5.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 5 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi5_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6005) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/arm_vsi6.py b/board/Corstone-320/vsi/python/arm_vsi6.py new file mode 100644 index 0000000..58b1184 --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi6.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 6 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi6_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6006) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/arm_vsi7.py b/board/Corstone-320/vsi/python/arm_vsi7.py new file mode 100644 index 0000000..cd32ab8 --- /dev/null +++ b/board/Corstone-320/vsi/python/arm_vsi7.py @@ -0,0 +1,217 @@ +# Copyright (c) 2021-2025 Arm Limited. All rights reserved. + +# Virtual Streaming Interface instance 7 Python script + +##@addtogroup arm_vsi_py_vstream_video +# @{ +# +##@package arm_vsi7_vstream_video +#Documentation for VSI vStream Video module. +# +#More details. + +import logging +import vsi_video + +logger = logging.getLogger(__name__) +vsi_video.logger = logger + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='Py: %(name)s : [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + + +# Video Server configuration +server_address = ('127.0.0.1', 6007) +server_authkey = 'vsi_video' + + +# IRQ registers +IRQ_Status = 0 + +# Timer registers +Timer_Control = 0 +Timer_Interval = 0 + +# Timer Control register definitions +Timer_Control_Run_Msk = 1<<0 +Timer_Control_Periodic_Msk = 1<<1 +Timer_Control_Trig_IRQ_Msk = 1<<2 +Timer_Control_Trig_DMA_Msk = 1<<3 + +# DMA registers +DMA_Control = 0 + +# DMA Control register definitions +DMA_Control_Enable_Msk = 1<<0 +DMA_Control_Direction_Msk = 1<<1 +DMA_Control_Direction_P2M = 0<<1 +DMA_Control_Direction_M2P = 1<<1 + +# User registers +Regs = [0] * 64 + +# Data buffer +Data = bytearray() + +# Streaming Server Connection Status +Server_Connected = False + + + +## Initialize +# @return None +def init(): + global Server_Connected + logger.info("init() called") + + Server_Connected = vsi_video.init(server_address, server_authkey) + + +## Read interrupt request (the VSI IRQ Status Register) +# @return value value read (32-bit) +def rdIRQ(): + global IRQ_Status + logger.info("rdIRQ() called") + + value = IRQ_Status + logger.debug(f"Read IRQ_Status: 0x{value:08X}") + + return value + + +## Write interrupt request (the VSI IRQ Status Register) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrIRQ(value): + global IRQ_Status + logger.info(f"wrIRQ(value=0x{value:08X}) called") + + IRQ_Status = value + logger.debug(f"wrIRQ: write IRQ_Status: 0x{value:08X}") + + return value + + +## Write Timer registers (the VSI Timer Registers) +# @param index Timer register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrTimer(index, value): + global Timer_Control, Timer_Interval + logger.info(f"wrTimer(index={index}, value=0x{value:08X}) called") + + if index == 0: + Timer_Control = value + logger.debug(f"wrTimer: write Timer_Control: 0x{value:08X}") + elif index == 1: + Timer_Interval = value + logger.debug(f"wrTimer: write Timer_Interval: 0x{value:08X}") + + return value + + +## Timer event (called at Timer Overflow) +# @return None +def timerEvent(): + logger.info("timerEvent() called") + + if Server_Connected: + vsi_video.timerEvent() + + +## Write DMA registers (the VSI DMA Registers) +# @param index DMA register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrDMA(index, value): + global DMA_Control + logger.info(f"wrDMA(index={index}, value=0x{value:08X}) called") + + if index == 0: + DMA_Control = value + logger.debug(f"wrDMA: write DMA_Control: 0x{value:08X}") + + return value + + +## Read data from peripheral for DMA P2M transfer (VSI DMA) +# @param size size of data to read (in bytes, multiple of 4) +# @return data data read (bytearray) +def rdDataDMA(size): + global Data + logger.info(f"rdDataDMA(size={size}) called") + + if Server_Connected: + Data = vsi_video.rdDataDMA(size) + + n = min(len(Data), size) + data = bytearray(size) + data[0:n] = Data[0:n] + logger.debug(f"rdDataDMA: read data ({size} bytes)") + + return data + + +## Write data to peripheral for DMA M2P transfer (VSI DMA) +# @param data data to write (bytearray) +# @param size size of data to write (in bytes, multiple of 4) +# @return None +def wrDataDMA(data, size): + global Data + logger.info(f"wrDataDMA(data={type(data).__name__}, size={size}) called") + + Data = data + logger.debug(f"wrDataDMA: write data ({size} bytes)") + + if Server_Connected: + vsi_video.wrDataDMA(data, size) + + return + + +## Read user registers (the VSI User Registers) +# @param index user register index (zero based) +# @return value value read (32-bit) +def rdRegs(index): + global Regs + logger.info(f"rdRegs(index={index}) called") + + if Server_Connected: + Regs[index] = vsi_video.rdRegs(index) + + value = Regs[index] + + # Log the value read from the register + logger.debug(f"rdRegs: read Regs[{index}]: 0x{value:08X}") + + return value + + +## Write user registers (the VSI User Registers) +# @param index user register index (zero based) +# @param value value to write (32-bit) +# @return value value written (32-bit) +def wrRegs(index, value): + global Regs + logger.info(f"wrRegs(index={index}, value=0x{value:08X}) called") + + if Server_Connected: + value = vsi_video.wrRegs(index, value) + + Regs[index] = value + + # Log the value written to the register + logger.debug(f"wrRegs: write Regs[{index}] = 0x{value:08X}") + + return value + + +## @} diff --git a/board/Corstone-320/vsi/python/vsi_audio.py b/board/Corstone-320/vsi/python/vsi_audio.py new file mode 100644 index 0000000..a71574a --- /dev/null +++ b/board/Corstone-320/vsi/python/vsi_audio.py @@ -0,0 +1,543 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) audio server. +# It allows configuration, streaming, and audio data transfer operations, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Audio:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Audio:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class AudioClient: + """ + Client for communicating with the VSI audio server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive audio data, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Audio format codes + self.PCM_S8 = 0 + self.PCM_S16LE = 1 + self.PCM_S24LE = 2 + self.PCM_S32LE = 3 + self.PCM_F32LE = 4 + + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI audio server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the audio stream (input/output). + Args: + mode: 1 for input, 2 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the audio streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the audio stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters on the server. + Args: + channels: Number of audio channels (1=mono, 2=stereo). + sample_rate: Sample rate in Hz (e.g., 44100, 48000). + sample_bits: Bit depth (8, 16, 24, 32). + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, channels, sample_rate, sample_bits]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the audio stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the audio stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readAudio(self, size): + """ + Request audio data from the server. + Args: + size: Number of bytes to read. + Returns: + tuple: (data, eos) where data is a Bytearray of audio data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.AUDIO_READ, size]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeAudio(self, data): + """ + Send audio data to the server. + Args: + data: Bytearray of audio data to write. + Returns: + None + """ + self.conn.send([self.AUDIO_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +CHANNELS = 1 # Regs[4] // Number of audio channels +SAMPLE_RATE = 16000 # Regs[5] // Sample rate +SAMPLE_BITS = 16 # Regs[6] // Bits per sample + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Audio.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Audio.configureStream(CHANNELS, SAMPLE_RATE, SAMPLE_BITS) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Audio.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Audio.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Audio.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Audio.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = CHANNELS + elif index == 5: + value = SAMPLE_RATE + elif index == 6: + value = SAMPLE_BITS + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, CHANNELS, SAMPLE_RATE, SAMPLE_BITS + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + CHANNELS = value + elif index == 5: + SAMPLE_RATE = value + elif index == 6: + SAMPLE_BITS = value + + return value diff --git a/board/Corstone-320/vsi/python/vsi_audio_server.py b/board/Corstone-320/vsi/python/vsi_audio_server.py new file mode 100644 index 0000000..dafa594 --- /dev/null +++ b/board/Corstone-320/vsi/python/vsi_audio_server.py @@ -0,0 +1,691 @@ +# Copyright (c) 2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Audio Server module + +try: + import argparse + import ipaddress + import logging + import time + import wave + from multiprocessing.connection import Listener + from pathlib import Path + + import pyaudio + import numpy as np +except ImportError as err: + print(f"VSI:Audio:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Audio:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Audio Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6001) +default_authkey = 'vsi_audio' + +# Supported file extensions +supported_files = ['wav'] + +# Mode Input/Output +MODE_AUDIO_NONE = 0 +MODE_AUDIO_INPUT = 1 +MODE_AUDIO_OUTPUT = 2 + +class AudioServer: + """Implements a TCP server for audio streaming and sample I/O. + + Supports both audio files and microphone/speaker devices as input/output. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing audio data), and performs the requested audio + operations using PyAudio and wave modules. + """ + def __init__(self, address, authkey): + """ + Initialize the AudioServer. + + Sets up command codes, audio format constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.AUDIO_READ = 7 + self.AUDIO_WRITE = 8 + self.CLOSE_SERVER = 9 + + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.eos = False + self.stream = None + self.wave_file = None + self.pyaudio_obj = pyaudio.PyAudio() + self.audio_buffer = bytearray() + self.chunk_size = 1024 + + # Stream configuration + self.channels = None + self.sample_rate = None + self.sample_bits = None + + def _setMode(self, mode): + """ + Set the stream mode to input (microphone/file) or output (speakers/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_AUDIO_INPUT: + self.mode = MODE_AUDIO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_AUDIO_OUTPUT: + self.mode = MODE_AUDIO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_AUDIO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_audio_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in supported_files: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_AUDIO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_AUDIO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, channels, sample_rate, sample_bits): + """ + Configure the audio stream parameters. + + Args: + channels: The number of audio channels (1=mono, 2=stereo). + sample_rate: The sample rate in Hz (8000, 16000, 44100, 48000). + sample_bits: The bit depth (8, 16, 24, 32). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits}") + + if channels <= 0 or sample_rate <= 0 or sample_bits <= 0: + logger.error(f"_configureStream: invalid argument (channels={channels}, sample_rate={sample_rate}, sample_bits={sample_bits})") + return False + + if sample_bits not in [8, 16, 24, 32]: + logger.error(f"_configureStream: unsupported sample_bits={sample_bits}") + return False + + self.channels = channels + self.sample_rate = sample_rate + self.sample_bits = sample_bits + + logger.info(f"_configureStream: stream configured to {self.channels} channels, {self.sample_rate}Hz, {self.sample_bits} bits") + + return True + + def _get_pyaudio_format(self): + """Get PyAudio format based on sample bits.""" + if self.sample_bits == 8: + return pyaudio.paUInt8 + elif self.sample_bits == 16: + return pyaudio.paInt16 + elif self.sample_bits == 24: + return pyaudio.paInt24 + elif self.sample_bits == 32: + return pyaudio.paInt32 + else: + return pyaudio.paInt16 # default + + def _scan_audio_devices(self): + """ + Scan and log available audio devices, separating input and output devices. + Returns: + Default device index for the current mode. + """ + if self.pyaudio_obj is None: + logger.error(" _scan_audio_devices: PyAudio object is not initialized") + return 0 + + logger.info("=== Available Audio Devices ===") + device_count = self.pyaudio_obj.get_device_count() + + input_devices = [] + output_devices = [] + + # Scan all devices + for i in range(device_count): + try: + info = self.pyaudio_obj.get_device_info_by_index(i) + host_api_info = self.pyaudio_obj.get_host_api_info_by_index(info['hostApi']) + + device_info = { + 'index': i, + 'name': info['name'], + 'max_input_channels': info['maxInputChannels'], + 'max_output_channels': info['maxOutputChannels'], + 'default_sample_rate': info['defaultSampleRate'], + 'host_api': host_api_info['name'] + } + + # Categorize devices + if info['maxInputChannels'] > 0: + input_devices.append(device_info) + if info['maxOutputChannels'] > 0: + output_devices.append(device_info) + + except Exception as e: + logger.warning(f"Device {i}: Error reading device info - {e}") + + # Retrieve default devices + try: + default_input = self.pyaudio_obj.get_default_input_device_info() + default_output = self.pyaudio_obj.get_default_output_device_info() + except Exception as e: + logger.warning(f"Error getting default devices: {e}") + + if (self.mode == MODE_AUDIO_INPUT): + # Log input devices + logger.info("--- INPUT DEVICES ---") + if input_devices: + for device in input_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Input Channels: {device['max_input_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No input devices found") + + logger.info(f"Default Input Device: {default_input['index']} - {default_input['name']}") + + rval = default_input['index'] + + if (self.mode == MODE_AUDIO_OUTPUT): + # Log output devices + logger.debug("--- OUTPUT DEVICES ---") + if output_devices: + for device in output_devices: + logger.debug(f"Device {device['index']}: {device['name']}") + logger.debug(f" - Output Channels: {device['max_output_channels']}") + logger.debug(f" - Sample Rate: {device['default_sample_rate']}") + else: + logger.info("No output devices found") + + logger.info(f"Default Output Device: {default_output['index']} - {default_output['name']}") + + rval = default_output['index'] + + return rval + + def _audio_callback_input(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio input stream. + """ + logger.debug(f"_audio_callback_input: received {len(in_data)} bytes") + + self.audio_buffer.extend(in_data) + return (None, pyaudio.paContinue) + + def _audio_callback_output(self, in_data, frame_count, time_info, status): + """ + Callback for PyAudio output stream. + """ + logger.debug(f"_audio_callback_output: requested {frame_count} frames") + + bytes_needed = frame_count * self.channels * (self.sample_bits // 8) + if len(self.audio_buffer) >= bytes_needed: + data = bytes(self.audio_buffer[:bytes_needed]) + del self.audio_buffer[:bytes_needed] + else: + # Not enough data, return silence + data = b'\x00' * bytes_needed + return (data, pyaudio.paContinue) + + def _enableStream(self): + """ + Enable the audio stream for input (microphone/file) or output (file/speakers). + + Initializes the PyAudio stream or wave file as needed. + Returns: + None + """ + if self.mode != MODE_AUDIO_INPUT and self.mode != MODE_AUDIO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.audio_buffer.clear() + + try: + if self.filename == None: + # Use microphone/speakers + if self.pyaudio_obj is None: + logger.error("_enableStream: PyAudio object is not initialized") + return + + audio_format = self._get_pyaudio_format() + + if self.mode == MODE_AUDIO_INPUT: + logger.debug("_enableStream: use microphone for input streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + input=True, + input_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_input + ) + self.stream.start_stream() + + elif self.mode == MODE_AUDIO_OUTPUT: + logger.debug("_enableStream: use speakers for output streaming") + self.stream = self.pyaudio_obj.open( + format=audio_format, + channels=self.channels, + rate=self.sample_rate, + output=True, + output_device_index=self.device, + frames_per_buffer=self.chunk_size, + stream_callback=self._audio_callback_output + ) + self.stream.start_stream() + + logger.info(f"_enableStream: audio device stream properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + else: + # Set file name string for audio file + file = str(self.filename.absolute()) + + logger.debug(f"_enableStream: use audio file: {file}") + + if self.mode == MODE_AUDIO_INPUT: + self.wave_file = wave.open(file, 'rb') + + # Verify file properties match configuration + file_channels = self.wave_file.getnchannels() + file_rate = self.wave_file.getframerate() + file_bits = self.wave_file.getsampwidth() * 8 + + if (file_channels != self.channels or file_rate != self.sample_rate or file_bits != self.sample_bits): + logger.warning(f"_enableStream: file properties ({file_channels}ch, {file_rate}Hz, {file_bits}bit) " + f"don't match configured ({self.channels}ch, {self.sample_rate}Hz, {self.sample_bits}bit)") + + logger.info(f"_enableStream: input file properties: channels={file_channels}, rate={file_rate}, bits={file_bits}") + + elif self.mode == MODE_AUDIO_OUTPUT: + self.wave_file = wave.open(file, 'wb') + self.wave_file.setnchannels(self.channels) + self.wave_file.setsampwidth(self.sample_bits // 8) + self.wave_file.setframerate(self.sample_rate) + + logger.info(f"_enableStream: output file properties: channels={self.channels}, rate={self.sample_rate}, bits={self.sample_bits}") + + self.active = True + logger.info("_enableStream: stream enabled") + + except Exception as e: + logger.error(f"_enableStream: failed to enable stream: {e}") + self._disableStream() + + def _disableStream(self): + """ + Disable the audio stream and release resources. + + Returns: + None + """ + self.active = False + + try: + if self.stream is not None: + if self.stream.is_active(): + self.stream.stop_stream() + self.stream.close() + self.stream = None + + if self.pyaudio_obj is not None: + self.pyaudio_obj.terminate() + self.pyaudio_obj = None + + if self.wave_file is not None: + self.wave_file.close() + self.wave_file = None + + except Exception as e: + logger.error(f"_disableStream: error during cleanup: {e}") + + logger.info("_disableStream: stream disabled") + + def _readAudio(self, size): + """ + Read audio data from the current source. + + Args: + size: Number of bytes to read. + Returns: + audio_data: The read audio data as a bytearray, or empty if no data is available. + """ + logger.debug(f"_readAudio: size={size} bytes") + + audio_data = bytearray() + + if not self.active: + logger.error("_readAudio: stream not active") + return audio_data + + if self.eos: + logger.debug("_readAudio: end of stream") + return audio_data + + try: + if self.filename == None: + # Read from microphone buffer + while len(self.audio_buffer) < size: + # Wait for enough data + time.sleep(0.01) # Wait 10ms + + # Now we have enough data + audio_data = bytearray(self.audio_buffer[:size]) + del self.audio_buffer[:size] + + logger.debug(f"_readAudio: read {len(audio_data)} bytes from microphone buffer") + + else: + # Read from wave file + frames_to_read = size // (self.channels * (self.sample_bits // 8)) + frames_data = self.wave_file.readframes(frames_to_read) + + if len(frames_data) > 0: + audio_data = bytearray(frames_data) + logger.debug(f"_readAudio: read {len(audio_data)} bytes from file") + else: + self.eos = True + logger.debug("_readAudio: end of file reached") + + except Exception as e: + logger.error(f"_readAudio: error reading audio data: {e}") + + return audio_data + + def _writeAudio(self, data): + """ + Write audio data to the output destination (file or speakers). + + Args: + data: The input audio data as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeAudio: audio data size={len(data)} bytes") + + if not self.active: + logger.error("_writeAudio: stream not active") + return + + try: + if self.filename == None: + # Write to speakers buffer + self.audio_buffer.extend(data) + logger.debug("_writeAudio: added data to speaker buffer") + + else: + # Write to wave file + self.wave_file.writeframes(data) + logger.debug("_writeAudio: wrote data to file") + + except Exception as e: + logger.error(f"_writeAudio: error writing audio data: {e}") + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write audio, close server. + Sends responses or audio data as appropriate. + """ + logger.info("Audio server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.AUDIO_READ: + size = payload[0] + audio_data = self._readAudio(size) + conn.send_bytes(audio_data) + conn.send(self.eos) + + elif cmd == self.AUDIO_WRITE: + audio_data = conn.recv_bytes() + self._writeAudio(audio_data) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + def stop(self): + """ + Stop the audio server. + + Releases all resources. + Returns: + None + """ + self._disableStream() + self.listener.close() + logger.info("Audio server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the audio server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Audio Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = AudioServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop() diff --git a/board/Corstone-320/vsi/python/vsi_video.py b/board/Corstone-320/vsi/python/vsi_video.py new file mode 100644 index 0000000..47a2af2 --- /dev/null +++ b/board/Corstone-320/vsi/python/vsi_video.py @@ -0,0 +1,547 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Client module +# This module provides a client interface for communicating with a VSI (Virtual Streaming Interface) video server. +# It allows configuration, streaming, and frame transfer operations for video data, typically used in hardware simulation or testing environments. + +try: + import time + import atexit + import logging + import subprocess + from multiprocessing.connection import Client, Connection + from os import path, getcwd + from os import name as os_name +except ImportError as err: + print(f"VSI:Video:ImportError: {err}") + raise +except Exception as e: + print(f"VSI:Video:Exception: {type(e).__name__}") + raise + +logger = logging.getLogger(__name__) + + +class VideoClient: + """ + Client for communicating with the VSI video server using Python's multiprocessing connection. + Provides methods to configure the stream, send/receive frames, and control the server. + """ + def __init__(self): + # Server command codes + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space codes + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Connection object + self.conn = None + + def connectToServer(self, address, authkey): + """ + Attempt to connect to the VSI video server at the given address with the provided authkey. + + Args: + address: The (IP, port) tuple for the server to connect to. + authkey: The authorization key for server connection. + Returns: + None + """ + for _ in range(50): + try: + self.conn = Client(address, authkey=authkey.encode('utf-8')) + if isinstance(self.conn, Connection): + break + else: + self.conn = None + except Exception: + self.conn = None + time.sleep(0.01) + + def setMode(self, mode): + """ + Set the mode of the video stream (input/output). + Args: + mode: 0 for input, 1 for output. + Returns: + True if the mode is valid, False otherwise. + """ + self.conn.send([self.SET_MODE, mode]) + mode_valid = self.conn.recv() + + return mode_valid + + def setDevice(self, device): + """ + Set the video streaming device index (input/output). + Args: + device: The device index value to set on the server. + Returns: + Device index actually set. + """ + self.conn.send([self.SET_DEVICE, device]) + device_index = self.conn.recv() + + return device_index + + def setFilename(self, filename): + """ + Set the filename for the video stream on the server. + Args: + filename: The name of the file to set on the server. + Returns: + True if the filename is valid, False otherwise. + """ + self.conn.send([self.SET_FILENAME, getcwd(), filename]) + filename_valid = self.conn.recv() + + return filename_valid + + def configureStream(self, frame_width, frame_height, frame_rate, color_format): + """ + Configure the video stream parameters on the server. + Args: + frame_width: Width of the video frame. + frame_height: Height of the video frame. + frame_rate: Frame rate in frames per second. + color_format: Color format code. + Returns: + True if configuration is valid, False otherwise. + """ + self.conn.send([self.STREAM_CONFIGURE, frame_width, frame_height, frame_rate, color_format]) + configuration_valid = self.conn.recv() + + return configuration_valid + + def enableStream(self): + """ + Enable the video stream on the server in the specified mode (input/output). + Returns: + `True` if the stream is active, `False` otherwise. + """ + self.conn.send([self.STREAM_ENABLE]) + stream_active = self.conn.recv() + + return stream_active + + def disableStream(self): + """ + Disable the video stream on the server. + Returns: + True if the stream is no longer active, False otherwise. + """ + self.conn.send([self.STREAM_DISABLE]) + stream_active = self.conn.recv() + + return stream_active + + def readFrame(self): + """ + Request a video frame from the server. + Returns: + tuple: (data, eos) where data is a Bytearray of frame data and eos is a Boolean indicating end-of-stream. + """ + self.conn.send([self.FRAME_READ]) + data = self.conn.recv_bytes() + eos = self.conn.recv() + + return data, eos + + def writeFrame(self, data): + """ + Send a video frame to the server. + Args: + data: Bytearray of frame data to write. + Returns: + None + """ + self.conn.send([self.FRAME_WRITE]) + self.conn.send_bytes(data) + + def closeServer(self): + """ + Close the connection to the server and request server shutdown. + Returns: + None + """ + try: + if isinstance(self.conn, Connection): + self.conn.send([self.CLOSE_SERVER]) + self.conn.close() + except Exception as e: + logger.error(f'Exception occurred on cleanup: {e}') + + + +# User register variables (simulate hardware registers for VSI peripheral) +CONTROL = 0 # Regs[0] // Control: enable, mode, continuous +STATUS = 0 # Regs[1] // Status: active, eos, file_name, file_valid +DEVICE = -1 # Regs[2] // Streaming device +FILENAME = "" # Regs[3] // Filename string array +FRAME_WIDTH = 300 # Regs[4] // Requested frame width +FRAME_HEIGHT = 300 # Regs[5] // Requested frame height +FRAME_RATE = 0 # Regs[6] // Frame rate +FRAME_COLOR = 0 # Regs[7] // Frame color space + + +# CONTROL register bit definitions +CONTROL_ENABLE_Pos = 0 +CONTROL_ENABLE_Msk = 1<> CONTROL_MODE_Pos) + if mode_valid: + logger.info("wrCONTROL: CONTROL register updated: MODE changed") + else: + # Reset Mode + Video.setMode(0) + value &= ~CONTROL_MODE_Msk + logger.error("wrCONTROL: CONTROL register updated: MODE cleared") + + if ((value ^ CONTROL) & CONTROL_ENABLE_Msk) != 0: + # ENABLE bit changed + if (value & CONTROL_ENABLE_Msk) != 0: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit set") + + # Configure stream + configuration_valid = Video.configureStream(FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR) + if configuration_valid: + # Configuration is valid, enable stream + server_active = Video.enableStream() + + if server_active: + STATUS |= STATUS_ACTIVE_Msk + STATUS &= ~STATUS_EOS_Msk + else: + logger.error("wrCONTROL: enable stream failed") + else: + logger.error("wrCONTROL: configure stream failed") + else: + logger.info("wrCONTROL: CONTROL register updated: ENABLE bit cleared") + Video.disableStream() + + STATUS &= ~STATUS_ACTIVE_Msk + logger.info("wrCONTROL: STATUS register updated: ACTIVE bit cleared") + + CONTROL = value + + +def rdSTATUS(): + """ + Read the STATUS register (user register). + + Returns: + status: Current STATUS register value (32-bit) + """ + global STATUS + logger.info(f"rdSTATUS: read STATUS: 0x{STATUS:08X}") + value = STATUS + + # Clear DATA bit on read of STATUS register + STATUS &= ~STATUS_DATA_Msk + logger.debug("rdSTATUS: STATUS register updated: DATA bit cleared") + + return value + + +def wrDEVICE(value): + """ + Write DEVICE register (user register). + Write is ignored if value to write equals to -1. + + Args: + value: Device index to set. + Returns: + None + """ + global DEVICE + DEVICE = Video.setDevice(value) + logger.info(f"wrDEVICE: DEVICE register set to {DEVICE}") + + +def rdFILENAME(): + """ + Read FILENAME register (user register). + + Returns: + filename_len: Length of the filename string + """ + global FILENAME + value = len(FILENAME) + logger.info(f"rdFILENAME: read FILENAME length: {value}") + return value + + +def wrFILENAME(value): + """ + Write FILENAME register (user register). + + Append character represented by argument `value` to the filename string. + Write 0 to set a null terminator. + First character received after null terminator starts a new filename. + Args: + value: Character to append (as string or int) + Returns: + None + """ + global FILENAME, STATUS + + char = chr(value) + + if STATUS & STATUS_FILE_NAME_Msk: + # Clear file related flags and reset filename + STATUS &= ~(STATUS_FILE_NAME_Msk | STATUS_FILE_VALID_Msk) + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME and FILE_VALID bits cleared") + + FILENAME = "" + logger.info("wrFILENAME: FILENAME register reset") + + if char != '\0': + # Got character to append + logger.debug(f"wrFILENAME: append {char} to filename") + FILENAME += f"{char}" + else: + # Got null terminator + logger.info(f"wrFILENAME: filename: {FILENAME}") + + STATUS |= STATUS_FILE_NAME_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_NAME bit set") + + if Video.setFilename(FILENAME) == True: + STATUS |= STATUS_FILE_VALID_Msk + logger.debug("wrFILENAME: STATUS register updated: FILE_VALID bit set") + else: + logger.error("wrFILENAME: Filename validation failed, file not found on server") + + +def rdRegs(index): + """ + Read user registers (the VSI User Registers). + + Read the value of a user register by index. + Args: + index: User register index (zero based) + Returns: + value: Value read (32-bit) + """ + global CONTROL, DEVICE, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + value = 0 + + if index == 0: + value = CONTROL + elif index == 1: + value = rdSTATUS() + elif index == 2: + value = DEVICE + elif index == 3: + value = rdFILENAME() + elif index == 4: + value = FRAME_WIDTH + elif index == 5: + value = FRAME_HEIGHT + elif index == 6: + value = FRAME_RATE + elif index == 7: + value = FRAME_COLOR + + return value + + +def wrRegs(index, value): + """ + Write user registers (the VSI User Registers). + + Write a value to a user register by index. + Args: + index: User register index (zero based) + value: Value to write (32-bit) + Returns: + value: Value written (32-bit) + """ + global STATUS, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, FRAME_COLOR + + if index == 0: + wrCONTROL(value) + elif index == 1: + value = STATUS + elif index == 2: + wrDEVICE(value) + elif index == 3: + wrFILENAME(value) + elif index == 4: + FRAME_WIDTH = value + elif index == 5: + FRAME_HEIGHT = value + elif index == 6: + FRAME_RATE = value + elif index == 7: + FRAME_COLOR = value + + return value diff --git a/board/Corstone-320/vsi/python/vsi_video_server.py b/board/Corstone-320/vsi/python/vsi_video_server.py new file mode 100644 index 0000000..3699eb3 --- /dev/null +++ b/board/Corstone-320/vsi/python/vsi_video_server.py @@ -0,0 +1,785 @@ +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Python VSI Video Server module + +try: + import argparse + import ipaddress + import logging + from multiprocessing.connection import Listener + from pathlib import Path + + import cv2 + import numpy as np +except ImportError as err: + print(f"VSI:Video:Server:ImportError: {err}") +except Exception as e: + print(f"VSI:Video:Server:Exception: {type(e).__name__}") + +logger = logging.getLogger(__name__) + +## Set verbosity level +#verbosity = logging.DEBUG +#verbosity = logging.INFO +#verbosity = logging.WARNING +verbosity = logging.ERROR + +# [debugging] Verbosity settings +level = { 10: "DEBUG", 20: "INFO", 30: "WARNING", 40: "ERROR" } +logging.basicConfig(format='VSI Video Server: [%(levelname)s]\t%(message)s', level = verbosity) +logger.info("Verbosity level is set to " + level[verbosity]) + +# Default Server configuration +default_address = ('127.0.0.1', 6000) +default_authkey = 'vsi_video' + +# Supported file extensions +video_file_extensions = ('wmv', 'avi', 'mp4') +image_file_extensions = ('bmp', 'png', 'jpg') +video_fourcc = {'wmv' : 'WMV1', 'avi' : 'MJPG', 'mp4' : 'mp4v'} + +# Mode Input/Output +MODE_VIDEO_NONE = 0 +MODE_VIDEO_INPUT = 1 +MODE_VIDEO_OUTPUT = 2 + +class VideoServer: + """Implements a TCP server for video streaming and frame I/O. + + Supports both video and image files as input/output, and can interface with a camera device. + Listens for commands from a client (such as setting mode, filename, configuring stream, + enabling/disabling stream, reading/writing frames), and performs the requested video + operations using OpenCV. + """ + def __init__(self, address, authkey): + """ + Initialize the VideoServer. + + Sets up command codes, color space constants, and initializes all state variables. + Creates a Listener object for incoming client connections. + Args: + address: The (IP, port) tuple for the server to listen on. + authkey: The authorization key for client connections. + Returns: + None + """ + # Server commands + self.SET_MODE = 1 + self.SET_DEVICE = 2 + self.SET_FILENAME = 3 + self.STREAM_CONFIGURE = 4 + self.STREAM_ENABLE = 5 + self.STREAM_DISABLE = 6 + self.FRAME_READ = 7 + self.FRAME_WRITE = 8 + self.CLOSE_SERVER = 9 + # Color space + self.GRAYSCALE8 = 0 + self.RGB888 = 1 + self.BGR565 = 2 + self.YUV420 = 3 + self.NV12 = 4 + self.NV21 = 5 + # Variables + self.listener = Listener(address, authkey=authkey.encode('utf-8')) + self.device = 0 + self.filename = None + self.mode = None + self.active = False + self.video = True + self.stream = None + self.frame_ratio = 0 + self.frame_drop = 0 + self.eos = False + # Stream configuration + self.frame_width = None + self.frame_height = None + self.frame_color = None + self.frame_rate = None + + + def _setMode(self, mode): + """ + Set the stream mode to input (camera/file) or output (display/file). + + Args: + mode: The I/O mode (input or output). + """ + mode_valid = False + + if mode == MODE_VIDEO_INPUT: + self.mode = MODE_VIDEO_INPUT + logger.info("_setMode: set stream mode to Input") + mode_valid = True + + elif mode == MODE_VIDEO_OUTPUT: + self.mode = MODE_VIDEO_OUTPUT + logger.info("_setMode: set stream mode to Output") + mode_valid = True + + else: + self.mode = MODE_VIDEO_NONE + logger.error("_setMode: invalid mode") + + return mode_valid + + def _setDevice(self, device): + """ + Set the streaming device index for input/output. + + Sets the device index to the specified value, or + scans for the default device if -1 (0xFFFFFFFF) is given. + + Args: + device: The device index to set. + Returns: + Device index actually set. + """ + logger.debug(f"_setDevice: device={device}") + + if (device == 4294967295): # -1 as unsigned 32-bit + # Set device index to point to default device for the selected mode + self.device = self._scan_video_devices() + else: + # Set device index to the specified value + self.device = device + + logger.info(f"_setDevice: streaming device set to {self.device}") + + return self.device + + def _setFilename(self, base_dir, filename): + """ + Set the filename for input or output file. + + Checks file extension to determine if file format is supported. + For input: verifies file exists and is supported. + For output: removes existing file if present. + Args: + base_dir: The base directory for the file. + filename: The name of the file (with extension). + Returns: + filename_valid: True if the filename is valid and set, False otherwise. + """ + logger.debug(f"_setFilename: base_dir={base_dir}, filename={filename}") + + filename_valid = False + + self.filename = None + + if filename == "": + # Empty filename is valid (use microphone/speakers) + return True + + work_dir = Path(base_dir) + file_name = Path(filename) + file_path = Path("") + + # Check if file extension is supported + ext = file_name.suffix.lstrip('.').lower() + if ext not in video_file_extensions + image_file_extensions: + logger.error(f"_setFilename: unsupported file extension={ext}") + return filename_valid + + # Check if filename is absolute path + if file_name.is_absolute(): + # Absolute path provided + file_path = file_name + logger.debug(f"_setFilename: absolute path provided, file path={file_path}") + else: + # Relative path provided, create full path + file_path = work_dir / file_name + logger.debug(f"_setFilename: relative path provided, file path={file_path}") + + # Normalize the file path + file_path = file_path.resolve() + + if self.mode == MODE_VIDEO_INPUT: + # Check if the file exists + if Path(file_path).exists(): + # File exists + filename_valid = True + else: + logger.error(f"_setFilename: file does not exist: {file_path}") + + if self.mode == MODE_VIDEO_OUTPUT: + # Check if the file exists + if Path(file_path).exists(): + # Remove existing file + Path(file_path).unlink(missing_ok=True) + + filename_valid = True + + if filename_valid: + # Set server side filename + self.filename = file_path + logger.info(f"_setFilename: filename set to {self.filename}") + + return filename_valid + + def _configureStream(self, frame_width, frame_height, frame_rate, frame_color): + """ + Configure the video stream parameters. + + Args: + frame_width: The desired frame width in pixels. + frame_height: The desired frame height in pixels. + frame_rate: The desired frame rate in frames per second. + frame_color: The desired frame color space (one of the defined constants). + Returns: + configuration_valid: True if the configuration is valid and set, False otherwise. + """ + logger.debug(f"_configureStream: frame_width={frame_width}, frame_height={frame_height}, frame_rate={frame_rate}, frame_color={frame_color}") + + if (frame_width == 0 or frame_height == 0 or frame_rate == 0): + logger.error(f"_configureStream: invalid argument (width={frame_width}, height={frame_height}, rate={frame_rate})") + return False + if frame_color not in (self.GRAYSCALE8, self.RGB888, self.BGR565, self.YUV420, self.NV12, self.NV21): + logger.error(f"_configureStream: invalid argument (color={frame_color})") + return False + + self.frame_width = frame_width + self.frame_height = frame_height + self.frame_rate = frame_rate + self.frame_color = frame_color + + logger.info(f"_configureStream: stream configured to {self.frame_width}x{self.frame_height}, fps={self.frame_rate}, color={self.frame_color}") + + return True + + def _scan_video_devices(self): + """ + Scan and log available video input devices. + Returns: + Default device index for the current mode. + """ + logger.info("=== Available Video Devices ===") + + available_devices = [] + + # Test device indices 0-1 (covers built-in webcam + external camera) + for device_index in range(2): + try: + cap = cv2.VideoCapture(device_index) + if cap.isOpened(): + + # Get device properties + width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + + device_info = { + 'index': device_index, + 'width': width, + 'height': height, + 'fps': fps, + } + available_devices.append(device_info) + + logger.info(f"Device {device_index}: {width}x{height} @ {fps:.1f}fps") + + cap.release() + except Exception as e: + logger.error(f"Error accessing device {device_index}: {e}") + + if not available_devices: + logger.warning("No video devices found") + return -1 + else: + logger.info(f"Found {len(available_devices)} input device(s)") + logger.info(f"Default Input Device: 0") + + return 0 + + def _enableStream(self): + """ + Enable the video stream for input (camera/file) or output (file/display). + + Initializes the OpenCV VideoCapture or VideoWriter as needed. + Handles both new and existing files, and sets up frame dropping if input FPS > requested FPS. + Returns: + None + """ + + if self.mode != MODE_VIDEO_INPUT and self.mode != MODE_VIDEO_OUTPUT: + logger.error("_enableStream: invalid mode") + return + + if self.active: + logger.info("_enableStream: stream already active") + return + + self.eos = False + self.frame_ratio = 0 + self.frame_drop = 0 + + if self.stream is not None: + self.stream.release() + self.stream = None + + if self.filename == None: + self.video = True + + if self.video: + if self.mode == MODE_VIDEO_INPUT: + # Input mode: read from camera or video file + if self.filename == None: + # No filename specified: use camera interface + logger.debug("_enableStream: use camera interface for input streaming") + self.stream = cv2.VideoCapture(self.device) + + if not self.stream.isOpened(): + logger.error("_enableStream: failed to open Camera interface") + return + else: + # Filename specified: use video file + logger.debug("_enableStream: use file interface for input streaming") + self.stream = cv2.VideoCapture(self.filename) + + # Display stream properties + logger.info(f"_enableStream: source stream properties: width={self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)}, height={self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)}, fps={self.stream.get(cv2.CAP_PROP_FPS)}") + + # Get the video stream FPS + video_fps = self.stream.get(cv2.CAP_PROP_FPS) + + if video_fps > self.frame_rate: + self.frame_ratio = video_fps / self.frame_rate + logger.debug(f"_enableStream: source/target frame ratio={self.frame_ratio}") + + elif self.mode == MODE_VIDEO_OUTPUT: + # Output mode: write to video file or display window + if self.filename != None: + # Filename specified: output to file + logger.debug("_enableStream: output stream to a file") + + extension = self.filename.suffix.lstrip('.').lower() + fourcc = cv2.VideoWriter_fourcc(*f'{video_fourcc[extension]}') + + self.stream = cv2.VideoWriter(self.filename, fourcc, self.frame_rate, (self.frame_width, self.frame_height)) + else: + logger.debug("_enableStream: output stream to display window") + + self.active = True + logger.info("_enableStream: stream enabled") + + def _disableStream(self): + """ + Disable the video stream and release OpenCV resources. + + For input streams, saves the current frame index for resuming later. + Returns: + None + """ + self.active = False + if self.stream is not None: + # Clean-up stream resources and invalidate object + self.stream.release() + self.stream = None + + logger.info("_disableStream: stream disabled") + + def __cropFrame(self, frame, target_aspect_ratio): + """ + Crop the input frame to match the specified aspect ratio. + + Args: + frame: The input frame (as NumPy array) to be cropped. + aspect_ratio: The target aspect ratio (width/height). + Returns: + frame: The cropped frame. + """ + logger.debug(f"__cropFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_aspect_ratio={target_aspect_ratio}") + + # NumPY array shape is (height, width, channels) + frame_h = frame.shape[0] + frame_w = frame.shape[1] + + frame_aspect_ratio = frame_w / frame_h + + if frame_aspect_ratio > target_aspect_ratio: + # Frame is wider than target -> crop left and right + new_w = int(frame_h * target_aspect_ratio) + left = (frame_w - new_w) // 2 + right = left + new_w + cropped = frame[:, left:right] + else: + # Frame is taller than target -> crop top and bottom + new_h = int(frame_w / target_aspect_ratio) + top = (frame_h - new_h) // 2 + bottom = top + new_h + cropped = frame[top:bottom, :] + + logger.debug(f"__cropFrame: cropped_size=({cropped.shape[1]}, {cropped.shape[0]})") + + return cropped + + def __resizeFrame(self, frame, target_width, target_height): + """ + Resize the input frame to the target width and height. + + Args: + frame: The input frame (as NumPy array) to be resized. + target_width: The target width in pixels. + target_height: The target height in pixels. + Returns: + frame: The resized frame. + """ + logger.debug(f"__resizeFrame: original_size=({frame.shape[1]}, {frame.shape[0]}), target_size=({target_width}, {target_height})") + + try: + frame = cv2.resize(frame, (target_width, target_height)) + except Exception as e: + logger.error(f"Error in resizeFrame(): {e}") + + logger.debug(f"__resizeFrame: resized_size=({frame.shape[1]}, {frame.shape[0]})") + + return frame + + def __convertToBGR(self, frame): + """ + Convert the input frame to BGR color space if needed. + + Args: + frame: The input frame (as NumPy array) to be converted. + Returns: + frame: The converted frame in BGR color space. + """ + if self.frame_color == self.RGB888: + # Convert RGB to BGR + logger.debug(f"__convertToBGR: converting frame from RGB to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) + elif self.frame_color == self.GRAYSCALE8: + # Convert Grayscale to BGR + logger.debug(f"__convertToBGR: converting frame from Grayscale to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) + elif self.frame_color == self.BGR565: + # Convert BGR565 to BGR + logger.debug(f"__convertToBGR: converting frame from BGR565 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR5652BGR) + elif self.frame_color == self.YUV420: + # Convert YUV420 to BGR + logger.debug(f"__convertToBGR: converting frame from YUV420 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_I420) + elif self.frame_color == self.NV12: + # Convert NV12 to BGR + logger.debug(f"__convertToBGR: converting frame from NV12 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV12) + elif self.frame_color == self.NV21: + # Convert NV21 to BGR + logger.debug(f"__convertToBGR: converting frame from NV21 to BGR") + frame = cv2.cvtColor(frame, cv2.COLOR_YUV2BGR_NV21) + + return frame + + def __convertFromBGR(self, frame): + """ + Convert the input BGR frame to the specified color space if needed. + + Args: + frame: The input frame (as NumPy array in BGR color space) to be converted. + Returns: + frame: The converted frame in the specified color space. + """ + if self.frame_color == self.RGB888: + # Convert BGR to RGB + logger.debug(f"__convertFromBGR: converting frame from BGR to RGB") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + elif self.frame_color == self.GRAYSCALE8: + # Convert BGR to Grayscale + logger.debug(f"__convertFromBGR: converting frame from BGR to Grayscale") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + elif self.frame_color == self.BGR565: + # Convert BGR to BGR565 + logger.debug(f"__convertFromBGR: converting frame from BGR to BGR565") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGR565) + elif self.frame_color == self.YUV420: + # Convert BGR to YUV420 + logger.debug(f"__convertFromBGR: converting frame from BGR to YUV420") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420) + elif self.frame_color == self.NV12: + # Convert BGR to NV12 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV12") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV12) + elif self.frame_color == self.NV21: + # Convert BGR to NV21 + logger.debug(f"__convertFromBGR: converting frame from BGR to NV21") + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_NV21) + + return frame + + # Read frame from source + def _readFrame(self): + """Read a single frame from the current video or image source. + + If the stream is not active or end-of-stream is reached, returns an empty bytearray. + For video sources, handles frame dropping to match requested frame rate. + For image sources, reads the image once and sets end-of-stream. + Resizes and converts color space as needed. + Returns: + frame: The read frame as a bytearray, or empty if no frame is available. + """ + frame = bytearray() + + # If the stream is not active, return empty frame + if not self.active: + logger.error("_readFrame: stream not active") + return frame + + # If end-of-stream has been reached, return empty frame + if self.eos: + logger.debug("_readFrame: end of stream reached") + return frame + + if self.video: + # Video source, read frame from the video stream + _, frame_in = self.stream.read() # Frame is numpy.ndarray, (height, width, channels), dtype=uint8 + + if frame_in is not None: + logger.debug(f"_readFrame: frame captured, size=({frame_in.shape[1]}, {frame_in.shape[0]})") + + # Handle frame dropping if input FPS > requested FPS + if self.frame_ratio > 1: + # Accumulate fractional frames to drop + self.frame_drop += (self.frame_ratio - 1) + + if self.frame_drop > 1: + logger.debug(f"_readFrame: frames to drop={self.frame_drop}") + drop = int(self.frame_drop // 1) + + # Drop the required number of frames to match requested FPS + for i in range(drop): + _, _ = self.stream.read() + logger.debug(f"_readFrame: frames dropped={drop}") + self.frame_drop -= drop + logger.debug(f"_readFrame: frames left to drop={self.frame_drop}") + else: + # Frame not read, mark end-of-stream + self.eos = True + logger.debug("_readFrame: end of stream.") + else: + # For image sources, read the image once and set end-of-stream + frame_in = cv2.imread(self.filename) + self.eos = True + logger.debug("_readFrame: end of stream.") + + if frame_in is not None: + target_width = self.frame_width + target_height = self.frame_height + + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size aspect ratio + target_aspect_ratio = target_width / target_height + frame_aspect_ratio = frame_in_width / frame_in_height + + if not np.isclose(frame_aspect_ratio, target_aspect_ratio, rtol=1e-3): + logger.debug(f"_readFrame: frame aspect ratio {frame_aspect_ratio:.2f} does not match target {target_aspect_ratio:.2f}, cropping frame") + frame_in = self.__cropFrame(frame_in, target_aspect_ratio) + + # Update frame size after cropping + frame_in_width = frame_in.shape[1] + frame_in_height = frame_in.shape[0] + + # Check the target frame size + if (frame_in_width != target_width) or (frame_in_height != target_height): + logger.debug(f"_readFrame: frame size ({frame_in_width}, {frame_in_height}) does not match target ({target_width}, {target_height}), resizing frame") + frame_in = self.__resizeFrame(frame_in, target_width, target_height) + + # Convert frame color space to target color space + frame_in = self.__convertFromBGR(frame_in) + + # Convert the frame to a bytearray for transmission + frame = bytearray(frame_in.tobytes()) + + return frame + + def _writeFrame(self, frame): + """ + Write a frame to the output destination (file or display window). + + If filename is empty, displays the frame in a window. + If filename is set and video mode, writes frame to video file. + If filename is set and image mode, saves frame as image file. + Args: + frame: The input frame as a bytearray to be written. + Returns: + None + """ + logger.debug(f"_writeFrame: frame size={len(frame)} bytes") + + # If the stream is not active, do nothing + if not self.active: + logger.error("_writeFrame: stream not active") + return + + try: + # Decode the frame from bytearray to a NumPy array + decoded_frame = np.frombuffer(frame, dtype=np.uint8) + + # Reshape the decoded frame to match the target resolution + decoded_frame = decoded_frame.reshape((self.frame_height, self.frame_width, 3)) + logger.debug(f"_writeFrame: decoded frame size=({decoded_frame.shape[1]}, {decoded_frame.shape[0]})") + + # Convert color space to BGR + frame_out = self.__convertToBGR(decoded_frame) + + if self.filename == None: + logger.debug("_writeFrame: display frame in window") + # If no filename, display the frame in a window + cv2.imshow(self.filename, frame_out) + cv2.waitKey(10) + else: + if self.video: + logger.debug("_writeFrame: write frame to video file") + # Write frame to video file + self.stream.write(np.uint8(frame_out)) + else: + logger.debug("_writeFrame: write frame as image file") + # Write frame as image file + cv2.imwrite(self.filename, frame_out) + + except Exception as e: + # Output exception debug information but continue + logger.error(f"Exception in _writeFrame: {type(e).__name__}: {e}", exc_info=True) + pass + + + def run(self): + """ + Main server loop. + + Waits for a client connection, then processes commands in a loop. + Handles all supported commands: set filename, configure stream, enable/disable stream, read/write frames, close server. + Sends responses or frame data as appropriate. + """ + logger.info("Video server started") + + try: + conn = self.listener.accept() + logger.info(f'Connection accepted {self.listener.address}') + except Exception: + logger.error("Connection not accepted") + return + + while True: + try: + recv = conn.recv() + except EOFError: + return + + cmd = recv[0] # Command + payload = recv[1:] # Payload + + if cmd == self.SET_MODE: + mode_valid = self._setMode(payload[0]) + conn.send(mode_valid) + + elif cmd == self.SET_DEVICE: + device_valid = self._setDevice(payload[0]) + conn.send(device_valid) + + elif cmd == self.SET_FILENAME: + filename_valid = self._setFilename(payload[0], payload[1]) + conn.send(filename_valid) + + elif cmd == self.STREAM_CONFIGURE: + configuration_valid = self._configureStream(payload[0], payload[1], payload[2], payload[3]) + conn.send(configuration_valid) + + elif cmd == self.STREAM_ENABLE: + self._enableStream() + conn.send(self.active) + + elif cmd == self.STREAM_DISABLE: + self._disableStream() + conn.send(self.active) + + elif cmd == self.FRAME_READ: + frame = self._readFrame() + conn.send_bytes(frame) + conn.send(self.eos) + + elif cmd == self.FRAME_WRITE: + frame = conn.recv_bytes() + self._writeFrame(frame) + + elif cmd == self.CLOSE_SERVER: + self.stop() + + + def stop(self): + """ + Stop the video server. + + Releases all resources and closes any open windows. + Returns: + None + """ + self._disableStream() + if (self.mode == MODE_VIDEO_OUTPUT) and (self.filename == None): + try: + cv2.destroyAllWindows() + except Exception: + pass + self.listener.close() + logger.info("Video server stopped") + + +def ip(ip): + """ + Validate that the input string is a valid IP address. + Args: + ip: The input IP address string to validate. + Returns: + ip: The validated IP address string. Raises an argparse.ArgumentTypeError if invalid. + """ + try: + _ = ipaddress.ip_address(ip) + return ip + except: + raise argparse.ArgumentTypeError(f"Invalid IP address: {ip}!") + +def parse_arguments(): + """ + Parse command-line arguments for the video server (IP, port, authkey). + Returns: + args: The parsed command-line arguments. + """ + formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=41) + parser = argparse.ArgumentParser(formatter_class=formatter, description="VSI Video Server") + + parser_optional = parser.add_argument_group("optional") + parser_optional.add_argument("--ip", dest="ip", metavar="", + help=f"Server IP address (default: {default_address[0]})", + type=ip, default=default_address[0]) + parser_optional.add_argument("--port", dest="port", metavar="", + help=f"TCP port (default: {default_address[1]})", + type=int, default=default_address[1]) + parser_optional.add_argument("--authkey", dest="authkey", metavar="", + help=f"Authorization key (default: {default_authkey})", + type=str, default=default_authkey) + + return parser.parse_args() + +if __name__ == '__main__': + args = parse_arguments() + Server = VideoServer((args.ip, args.port), args.authkey) + try: + Server.run() + except KeyboardInterrupt: + Server.stop()