You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by le...@apache.org on 2022/02/10 09:12:24 UTC

[tvm] branch main updated: Add FreeRTOS variant of NPU demo (#10004)

This is an automated email from the ASF dual-hosted git repository.

leandron pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new e50a923  Add FreeRTOS variant of NPU demo (#10004)
e50a923 is described below

commit e50a923671905f59bd34bd2146e0cfee477242df
Author: Christopher Sidebottom <ch...@arm.com>
AuthorDate: Thu Feb 10 09:11:58 2022 +0000

    Add FreeRTOS variant of NPU demo (#10004)
    
    * Add FreeRTOS variant of NPU demo
    
    This adds an extra flag to the existing NPU demo that runs it using the
    FreeRTOS kernel task scheduling and queues.
    
    * Add FreeRTOS notes to tutorial
    
    * Update FreeRTOS demo to run in demo script
    
    Also, minor text fixes.
    
    * Minor text fixes
    
    * Fix docs formatting
---
 apps/microtvm/ethosu/.gitignore                    |   3 +
 apps/microtvm/ethosu/Makefile                      |  21 +++-
 apps/microtvm/ethosu/README.md                     |   7 +-
 apps/microtvm/ethosu/include/FreeRTOSConfig.h      | 112 ++++++++++++++++++
 apps/microtvm/ethosu/include/tvm_runtime.h         |   2 +-
 apps/microtvm/ethosu/run_demo.sh                   |  14 ++-
 .../ethosu/src/{demo.c => demo_bare_metal.c}       |   0
 apps/microtvm/ethosu/src/demo_freertos.c           | 131 +++++++++++++++++++++
 apps/microtvm/zephyr_cmsisnn/run_demo.sh           |   1 -
 gallery/how_to/work_with_microtvm/micro_ethosu.py  |  13 ++
 tests/scripts/task_cpp_unittest.sh                 |  14 ---
 tests/scripts/task_demo_microtvm.sh                |   9 ++
 12 files changed, 307 insertions(+), 20 deletions(-)

diff --git a/apps/microtvm/ethosu/.gitignore b/apps/microtvm/ethosu/.gitignore
new file mode 100644
index 0000000..3ef8f08
--- /dev/null
+++ b/apps/microtvm/ethosu/.gitignore
@@ -0,0 +1,3 @@
+include/inputs.h
+include/outputs.h
+include/labels.h
diff --git a/apps/microtvm/ethosu/Makefile b/apps/microtvm/ethosu/Makefile
index d76bf90..1c4af77 100644
--- a/apps/microtvm/ethosu/Makefile
+++ b/apps/microtvm/ethosu/Makefile
@@ -58,6 +58,23 @@ $(else)
 QUIET ?= @
 $(endif)
 
+ifdef FREERTOS_PATH
+DEMO_MAIN = src/demo_freertos.c
+FREERTOS_KERNEL = $(FREERTOS_PATH)/FreeRTOS/Source
+FREERTOS_FLAGS = -I$(FREERTOS_KERNEL)/include/ \
+	-I$(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/
+FREERTOS_SOURCES = $(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/port.c \
+	$(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c \
+	$(FREERTOS_KERNEL)/tasks.c \
+	$(FREERTOS_KERNEL)/list.c \
+	$(FREERTOS_KERNEL)/queue.c \
+	$(FREERTOS_KERNEL)/timers.c \
+	$(FREERTOS_KERNEL)/event_groups.c \
+	$(FREERTOS_KERNEL)/portable/MemMang/heap_3.c
+else
+DEMO_MAIN = src/demo_bare_metal.c
+endif
+
 CODEGEN_SRCS = $(wildcard $(abspath $(BUILD_DIR))/codegen/host/src/*.c)
 CODEGEN_OBJS = $(subst .c,.o,$(CODEGEN_SRCS))
 CMSIS_STARTUP_SRCS = $(wildcard ${CMSIS_PATH}/Device/ARM/${ARM_CPU}/Source/*.c)
@@ -99,9 +116,9 @@ ${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a:
 	$(QUIET)cd $(abspath $(BUILD_DIR)/cmsis_nn) && $(MAKE) CMSISNNSoftmax	
 
 # Build demo application
-$(BUILD_DIR)/demo: src/demo.c src/tvm_ethosu_runtime.c $(UART_SRCS) $(BUILD_DIR)/stack_allocator.o $(BUILD_DIR)/crt_backend_api.o ${BUILD_DIR}/libcodegen.a ${BUILD_DIR}/libcmsis_startup.a ${BUILD_DIR}/ethosu_core_driver/libethosu_core_driver.a ${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a
+$(BUILD_DIR)/demo: $(DEMO_MAIN) src/tvm_ethosu_runtime.c $(FREERTOS_SOURCES) $(UART_SRCS) $(BUILD_DIR)/stack_allocator.o $(BUILD_DIR)/crt_backend_api.o ${BUILD_DIR}/libcodegen.a ${BUILD_DIR}/libcmsis_startup.a ${BUILD_DIR}/ethosu_core_driver/libethosu_core_driver.a ${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a
 	$(QUIET)mkdir -p $(@D)
-	$(QUIET)$(CC) $(PKG_CFLAGS) -o $@ $^ $(PKG_LDFLAGS)
+	$(QUIET)$(CC) $(PKG_CFLAGS) $(FREERTOS_FLAGS) -o $@ $^ $(PKG_LDFLAGS)
 
 clean:
 	$(QUIET)rm -rf $(BUILD_DIR)/codegen
diff --git a/apps/microtvm/ethosu/README.md b/apps/microtvm/ethosu/README.md
index e681b29..1f08928 100644
--- a/apps/microtvm/ethosu/README.md
+++ b/apps/microtvm/ethosu/README.md
@@ -58,12 +58,17 @@ export PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4:/opt/arm/cmake/
 
 Running the demo application
 ----------------------------
-Type the following command to run the demo application:
+Type the following command to run the bare metal demo application ([src/demo_bare_metal.c](./src/demo_bare_metal.c)):
 
 ```bash
 ./run_demo.sh
 ```
 
+To run the demo using FreeRTOS task scheduling and queues ([src/demo_freertos.c](./src/demo_freertos.c)), specify the path to FreeRTOS using `--freertos_path`, for example:
+```
+./run_demo.sh --freertos_path /opt/freertos/FreeRTOSv202112.00/
+```
+
 If the Ethos(TM)-U driver and/or CMSIS have not been installed in /opt/arm/ethosu then
 the locations for these can be specified as arguments to run_demo.sh, for example:
 
diff --git a/apps/microtvm/ethosu/include/FreeRTOSConfig.h b/apps/microtvm/ethosu/include/FreeRTOSConfig.h
new file mode 100644
index 0000000..a123581
--- /dev/null
+++ b/apps/microtvm/ethosu/include/FreeRTOSConfig.h
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/* Please refer to http://www.freertos.org/a00110.html for refernce. */
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+/******************************************************************************
+ * Defines
+ **********SYSTEM_CORE_CLOCK********************************************************************/
+/* Hardware features */
+#define configENABLE_MPU 0
+#define configENABLE_FPU 0
+#define configENABLE_TRUSTZONE 0
+/* Scheduling */
+#define configCPU_CLOCK_HZ 25000000
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#define configUSE_PREEMPTION 1
+#define configUSE_TIME_SLICING 0
+#define configMAX_PRIORITIES 5
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_16_BIT_TICKS 0
+#define configRUN_FREERTOS_SECURE_ONLY 1
+/* Stack and heap */
+#define configMINIMAL_STACK_SIZE (uint16_t)128
+#define configMINIMAL_SECURE_STACK_SIZE 1024
+#define configTOTAL_HEAP_SIZE (size_t)(50 * 1024)
+#define configMAX_TASK_NAME_LEN 12
+/* OS features */
+#define configUSE_MUTEXES 1
+#define configUSE_TICKLESS_IDLE 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_NEWLIB_REENTRANT 0
+#define configUSE_CO_ROUTINES 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configUSE_TRACE_FACILITY 1
+/* Hooks */
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configUSE_MALLOC_FAILED_HOOK 0
+/* Debug features */
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#define configASSERT(x)       \
+  if ((x) == 0) {             \
+    taskDISABLE_INTERRUPTS(); \
+    for (;;)                  \
+      ;                       \
+  }
+#define configQUEUE_REGISTRY_SIZE 0
+/* Timers and queues */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
+#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
+#define configTIMER_QUEUE_LENGTH 5
+/* Task settings */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 0
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTaskResumeFromISR 0
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_xTaskGetSchedulerState 0
+#define INCLUDE_xSemaphoreGetMutexHolder 0
+#define INCLUDE_xTimerPendFunctionCall 1
+#define configUSE_STATS_FORMATTING_FUNCTIONS 1
+#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2048
+#ifdef __NVIC_PRIO_BITS
+#define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+#define configPRIO_BITS 3
+#endif
+/* Interrupt settings */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
+#define configKERNEL_INTERRUPT_PRIORITY \
+  (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
+  (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
+#ifndef __IASMARM__
+#define configGENERATE_RUN_TIME_STATS 0
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#define portGET_RUN_TIME_COUNTER_VALUE() 0
+#define configTICK_RATE_HZ (TickType_t)1000
+#endif /* __IASMARM__ */
+#define xPortPendSVHandler PendSV_Handler
+#define vPortSVCHandler SVC_Handler
+#define xPortSysTickHandler SysTick_Handler
+#endif /* FREERTOS_CONFIG_H */
diff --git a/apps/microtvm/ethosu/include/tvm_runtime.h b/apps/microtvm/ethosu/include/tvm_runtime.h
index 09d766e..3ab9981 100644
--- a/apps/microtvm/ethosu/include/tvm_runtime.h
+++ b/apps/microtvm/ethosu/include/tvm_runtime.h
@@ -57,4 +57,4 @@ TVM_DLL int TVMFuncRegisterGlobal(const char* name, TVMFunctionHandle f, int ove
 
 #ifdef __cplusplus
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/apps/microtvm/ethosu/run_demo.sh b/apps/microtvm/ethosu/run_demo.sh
index 7c2bb09..18d82f7 100755
--- a/apps/microtvm/ethosu/run_demo.sh
+++ b/apps/microtvm/ethosu/run_demo.sh
@@ -71,6 +71,18 @@ while (( $# )); do
             fi
             ;;
 
+        --freertos_path)
+            if [ $# -gt 1 ]
+            then
+                export FREERTOS_PATH="$2"
+                shift 2
+            else
+                echo 'ERROR: --freertos_path requires a non-empty argument' >&2
+                show_usage >&2
+                exit 1
+            fi
+            ;;
+
         --ethosu_platform_path)
             if [ $# -gt 1 ]
             then
@@ -105,7 +117,7 @@ while (( $# )); do
                 show_usage >&2
                 exit 1
             fi
-            ;;            
+            ;;
 
         -*|--*)
             echo "Error: Unknown flag: $1" >&2
diff --git a/apps/microtvm/ethosu/src/demo.c b/apps/microtvm/ethosu/src/demo_bare_metal.c
similarity index 100%
rename from apps/microtvm/ethosu/src/demo.c
rename to apps/microtvm/ethosu/src/demo_bare_metal.c
diff --git a/apps/microtvm/ethosu/src/demo_freertos.c b/apps/microtvm/ethosu/src/demo_freertos.c
new file mode 100644
index 0000000..cd5b76b
--- /dev/null
+++ b/apps/microtvm/ethosu/src/demo_freertos.c
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <FreeRTOS.h>
+#include <queue.h>
+#include <stdio.h>
+#include <task.h>
+#include <tvm_runtime.h>
+
+#include "ethosu_mod.h"
+#include "uart.h"
+
+// Header files generated by convert_image.py and convert_labels.py
+#include "inputs.h"
+#include "labels.h"
+#include "outputs.h"
+
+static void prvInferenceTask(void* pvParameters);
+static void prvDataCollectionTask(void* pvParameters);
+
+#define mainQUEUE_INFERENCE_TASK_PRIORITY (tskIDLE_PRIORITY + 3)
+#define mainQUEUE_INFERENCE_TASK_STACK_SIZE 4096
+#define mainQUEUE_DATA_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
+#define mainQUEUE_DATA_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
+#define mainQUEUE_LENGTH (1)
+#define mainQUEUE_SEND_FREQUENCY_MS (100 / portTICK_PERIOD_MS)
+
+/* The queue used to pass data to run through our model */
+static QueueHandle_t xQueue = NULL;
+
+int main(void) {
+  // Platform UART
+  uart_init();
+  // NPU
+  EthosuInit();
+  // TVM Memory Manager
+  StackMemoryManager_Init(&app_workspace, g_aot_memory, WORKSPACE_SIZE);
+
+  // Queue for inferences
+  xQueue = xQueueCreate(mainQUEUE_LENGTH, sizeof(uint8_t*));
+
+  if (xQueue != NULL) {
+    // Inference task
+    xTaskCreate(prvInferenceTask, "Inference", mainQUEUE_INFERENCE_TASK_STACK_SIZE, NULL,
+                mainQUEUE_INFERENCE_TASK_PRIORITY, NULL);
+
+    // Data collector task
+    xTaskCreate(prvDataCollectionTask, "Data", mainQUEUE_DATA_TASK_STACK_SIZE, NULL,
+                mainQUEUE_DATA_TASK_PRIORITY, NULL);
+
+    // Start the task scheduling
+    vTaskStartScheduler();
+  }
+
+  // The task scheduler should take over before this is reached
+  printf("Unreachable code reached!\n");
+}
+
+/*
+ * This task emulates collection of data and sending it to another inference task
+ * for processing
+ */
+static void prvDataCollectionTask(void* pvParameters) {
+  // Unused
+  (void)pvParameters;
+
+  // Working
+  vTaskDelay(mainQUEUE_SEND_FREQUENCY_MS);
+
+  // Construct pointer to copy to queue
+  uint8_t** pucInputData = &input;
+  xQueueSend(xQueue, &pucInputData, 0U);
+}
+
+/*
+ * This task emulates the inference of data sent by the collector task
+ */
+static void prvInferenceTask(void* pvParameters) {
+  uint8_t* pucReceivedData;
+
+  // Unused
+  (void)pvParameters;
+
+  // Wait for data collection
+  xQueueReceive(xQueue, &pucReceivedData, portMAX_DELAY);
+
+  // Print output of inference and exit task
+  printf("Running inference\n");
+  struct tvmgen_default_inputs xInputs = {
+      .tfl_quantize = pucReceivedData,
+  };
+  struct tvmgen_default_outputs xOutputs = {
+      .output = output,
+  };
+  struct ethosu_driver* xDriver = ethosu_reserve_driver();
+  struct tvmgen_default_devices xDevices = {
+      .ethos_u = xDriver,
+  };
+  tvmgen_default_run(&xInputs, &xOutputs, &xDevices);
+  ethosu_release_driver(xDriver);
+
+  // Calculate index of max value
+  int8_t ucMaxValue = -128;
+  int32_t lMaxIndex = -1;
+  for (unsigned int i = 0; i < output_len; ++i) {
+    if (output[i] > ucMaxValue) {
+      ucMaxValue = output[i];
+      lMaxIndex = i;
+    }
+  }
+  printf("The image has been classified as '%s'\n", labels[lMaxIndex]);
+
+  // The FVP will shut down when it receives "EXITTHESIM" on the UART
+  printf("EXITTHESIM\n");
+}
diff --git a/apps/microtvm/zephyr_cmsisnn/run_demo.sh b/apps/microtvm/zephyr_cmsisnn/run_demo.sh
index 13d163b..6588b56 100755
--- a/apps/microtvm/zephyr_cmsisnn/run_demo.sh
+++ b/apps/microtvm/zephyr_cmsisnn/run_demo.sh
@@ -45,7 +45,6 @@ export ARMFVP_BIN_PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4/
 west zephyr-export
 west build
 west build -t run &> ${LOGDIR}/west.log &
-WEST_PID=$! 
 
 # Wait for "exit" keyword 
 until grep -m 1 "exit" ${LOGDIR}/west.log; do sleep 1 ; done
diff --git a/gallery/how_to/work_with_microtvm/micro_ethosu.py b/gallery/how_to/work_with_microtvm/micro_ethosu.py
index 848db2e..ef34c7d 100644
--- a/gallery/how_to/work_with_microtvm/micro_ethosu.py
+++ b/gallery/how_to/work_with_microtvm/micro_ethosu.py
@@ -412,6 +412,12 @@ TVM to offload operators to the Ethos(TM)-U55 where possible.
 # `include files <https://github.com/apache/tvm/tree/main/apps/microtvm/ethosu/include>`_
 
 ################################################################################
+# .. note::
+#
+#   If you'd like to use FreeRTOS for task scheduling and queues, a sample application can be found here
+#   `demo_freertos.c <https://github.com/apache/tvm/blob/main/apps/microtvm/ethosu/src/demo_freertos.c>`
+
+################################################################################
 # Creating the linker script
 # --------------------------
 #
@@ -454,6 +460,13 @@ TVM to offload operators to the Ethos(TM)-U55 where possible.
 # `Makefile <https://github.com/apache/tvm/blob/main/apps/microtvm/ethosu/Makefile>`_
 
 ################################################################################
+# .. note::
+#
+#    If you're using FreeRTOS, the Makefile builds it from the specified FREERTOS_PATH:
+#     ``make FREERTOS_PATH=<FreeRTOS directory>``
+#
+
+################################################################################
 # Running the demo application
 # ----------------------------
 #
diff --git a/tests/scripts/task_cpp_unittest.sh b/tests/scripts/task_cpp_unittest.sh
index e6c3669..3df7b58 100755
--- a/tests/scripts/task_cpp_unittest.sh
+++ b/tests/scripts/task_cpp_unittest.sh
@@ -45,17 +45,3 @@ cd apps/bundle_deploy
 rm -rf build
 make test_dynamic test_static
 cd ../..
-
-# Test Arm(R) Cortex(R)-M55 CPU and Ethos(TM)-U55 NPU demo app
-FVP_PATH="/opt/arm/FVP_Corstone_SSE-300"
-
-# TODO(@grant-arm): Remove once ci_cpu docker image has been updated to FVP_Corstone_SSE
-if test ! -d $FVP_PATH; then
-    FVP_PATH="/opt/arm/FVP_Corstone_SSE-300_Ethos-U55"
-fi
-
-if test -d $FVP_PATH && pip3 list | grep vela; then
-    cd apps/microtvm/ethosu
-    ./run_demo.sh --fvp_path $FVP_PATH --cmake_path /opt/arm/cmake/bin/cmake
-    cd ../../..
-fi
diff --git a/tests/scripts/task_demo_microtvm.sh b/tests/scripts/task_demo_microtvm.sh
index 383e693..c569f6c 100755
--- a/tests/scripts/task_demo_microtvm.sh
+++ b/tests/scripts/task_demo_microtvm.sh
@@ -21,3 +21,12 @@ set -euxo pipefail
 pushd apps/microtvm/zephyr_cmsisnn
 ./run_demo.sh
 popd
+
+pushd apps/microtvm/ethosu
+FVP_PATH="/opt/arm/FVP_Corstone_SSE-300_Ethos-U55"
+CMAKE_PATH="/opt/arm/cmake/bin/cmake"
+FREERTOS_PATH="/opt/freertos/FreeRTOSv202112.00"
+
+./run_demo.sh --fvp_path $FVP_PATH --cmake_path $CMAKE_PATH
+./run_demo.sh --fvp_path $FVP_PATH --cmake_path $CMAKE_PATH --freertos_path $FREERTOS_PATH
+popd