Skip to content

Commit 996a61c

Browse files
Mousiusylc
authored andcommitted
Add FreeRTOS variant of NPU demo (apache#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
1 parent 341a0a2 commit 996a61c

12 files changed

Lines changed: 307 additions & 20 deletions

File tree

apps/microtvm/ethosu/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include/inputs.h
2+
include/outputs.h
3+
include/labels.h

apps/microtvm/ethosu/Makefile

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ $(else)
5858
QUIET ?= @
5959
$(endif)
6060

61+
ifdef FREERTOS_PATH
62+
DEMO_MAIN = src/demo_freertos.c
63+
FREERTOS_KERNEL = $(FREERTOS_PATH)/FreeRTOS/Source
64+
FREERTOS_FLAGS = -I$(FREERTOS_KERNEL)/include/ \
65+
-I$(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/
66+
FREERTOS_SOURCES = $(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/port.c \
67+
$(FREERTOS_KERNEL)/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c \
68+
$(FREERTOS_KERNEL)/tasks.c \
69+
$(FREERTOS_KERNEL)/list.c \
70+
$(FREERTOS_KERNEL)/queue.c \
71+
$(FREERTOS_KERNEL)/timers.c \
72+
$(FREERTOS_KERNEL)/event_groups.c \
73+
$(FREERTOS_KERNEL)/portable/MemMang/heap_3.c
74+
else
75+
DEMO_MAIN = src/demo_bare_metal.c
76+
endif
77+
6178
CODEGEN_SRCS = $(wildcard $(abspath $(BUILD_DIR))/codegen/host/src/*.c)
6279
CODEGEN_OBJS = $(subst .c,.o,$(CODEGEN_SRCS))
6380
CMSIS_STARTUP_SRCS = $(wildcard ${CMSIS_PATH}/Device/ARM/${ARM_CPU}/Source/*.c)
@@ -99,9 +116,9 @@ ${BUILD_DIR}/cmsis_nn/Source/SoftmaxFunctions/libCMSISNNSoftmax.a:
99116
$(QUIET)cd $(abspath $(BUILD_DIR)/cmsis_nn) && $(MAKE) CMSISNNSoftmax
100117

101118
# Build demo application
102-
$(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
119+
$(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
103120
$(QUIET)mkdir -p $(@D)
104-
$(QUIET)$(CC) $(PKG_CFLAGS) -o $@ $^ $(PKG_LDFLAGS)
121+
$(QUIET)$(CC) $(PKG_CFLAGS) $(FREERTOS_FLAGS) -o $@ $^ $(PKG_LDFLAGS)
105122

106123
clean:
107124
$(QUIET)rm -rf $(BUILD_DIR)/codegen

apps/microtvm/ethosu/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,17 @@ export PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4:/opt/arm/cmake/
5858
5959
Running the demo application
6060
----------------------------
61-
Type the following command to run the demo application:
61+
Type the following command to run the bare metal demo application ([src/demo_bare_metal.c](./src/demo_bare_metal.c)):
6262
6363
```bash
6464
./run_demo.sh
6565
```
6666
67+
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:
68+
```
69+
./run_demo.sh --freertos_path /opt/freertos/FreeRTOSv202112.00/
70+
```
71+
6772
If the Ethos(TM)-U driver and/or CMSIS have not been installed in /opt/arm/ethosu then
6873
the locations for these can be specified as arguments to run_demo.sh, for example:
6974
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/* Please refer to http://www.freertos.org/a00110.html for refernce. */
21+
#ifndef FREERTOS_CONFIG_H
22+
#define FREERTOS_CONFIG_H
23+
/******************************************************************************
24+
* Defines
25+
**********SYSTEM_CORE_CLOCK********************************************************************/
26+
/* Hardware features */
27+
#define configENABLE_MPU 0
28+
#define configENABLE_FPU 0
29+
#define configENABLE_TRUSTZONE 0
30+
/* Scheduling */
31+
#define configCPU_CLOCK_HZ 25000000
32+
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
33+
#define configUSE_PREEMPTION 1
34+
#define configUSE_TIME_SLICING 0
35+
#define configMAX_PRIORITIES 5
36+
#define configIDLE_SHOULD_YIELD 1
37+
#define configUSE_16_BIT_TICKS 0
38+
#define configRUN_FREERTOS_SECURE_ONLY 1
39+
/* Stack and heap */
40+
#define configMINIMAL_STACK_SIZE (uint16_t)128
41+
#define configMINIMAL_SECURE_STACK_SIZE 1024
42+
#define configTOTAL_HEAP_SIZE (size_t)(50 * 1024)
43+
#define configMAX_TASK_NAME_LEN 12
44+
/* OS features */
45+
#define configUSE_MUTEXES 1
46+
#define configUSE_TICKLESS_IDLE 1
47+
#define configUSE_APPLICATION_TASK_TAG 0
48+
#define configUSE_NEWLIB_REENTRANT 0
49+
#define configUSE_CO_ROUTINES 0
50+
#define configUSE_COUNTING_SEMAPHORES 1
51+
#define configUSE_RECURSIVE_MUTEXES 1
52+
#define configUSE_QUEUE_SETS 0
53+
#define configUSE_TASK_NOTIFICATIONS 1
54+
#define configUSE_TRACE_FACILITY 1
55+
/* Hooks */
56+
#define configUSE_IDLE_HOOK 0
57+
#define configUSE_TICK_HOOK 0
58+
#define configUSE_MALLOC_FAILED_HOOK 0
59+
/* Debug features */
60+
#define configCHECK_FOR_STACK_OVERFLOW 0
61+
#define configASSERT(x) \
62+
if ((x) == 0) { \
63+
taskDISABLE_INTERRUPTS(); \
64+
for (;;) \
65+
; \
66+
}
67+
#define configQUEUE_REGISTRY_SIZE 0
68+
/* Timers and queues */
69+
#define configUSE_TIMERS 1
70+
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
71+
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
72+
#define configTIMER_QUEUE_LENGTH 5
73+
/* Task settings */
74+
#define INCLUDE_vTaskPrioritySet 1
75+
#define INCLUDE_uxTaskPriorityGet 1
76+
#define INCLUDE_vTaskDelete 1
77+
#define INCLUDE_vTaskCleanUpResources 0
78+
#define INCLUDE_vTaskSuspend 1
79+
#define INCLUDE_vTaskDelayUntil 1
80+
#define INCLUDE_vTaskDelay 1
81+
#define INCLUDE_uxTaskGetStackHighWaterMark 0
82+
#define INCLUDE_xTaskGetIdleTaskHandle 0
83+
#define INCLUDE_eTaskGetState 1
84+
#define INCLUDE_xTaskResumeFromISR 0
85+
#define INCLUDE_xTaskGetCurrentTaskHandle 1
86+
#define INCLUDE_xTaskGetSchedulerState 0
87+
#define INCLUDE_xSemaphoreGetMutexHolder 0
88+
#define INCLUDE_xTimerPendFunctionCall 1
89+
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
90+
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2048
91+
#ifdef __NVIC_PRIO_BITS
92+
#define configPRIO_BITS __NVIC_PRIO_BITS
93+
#else
94+
#define configPRIO_BITS 3
95+
#endif
96+
/* Interrupt settings */
97+
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
98+
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
99+
#define configKERNEL_INTERRUPT_PRIORITY \
100+
(configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
101+
#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
102+
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
103+
#ifndef __IASMARM__
104+
#define configGENERATE_RUN_TIME_STATS 0
105+
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
106+
#define portGET_RUN_TIME_COUNTER_VALUE() 0
107+
#define configTICK_RATE_HZ (TickType_t)1000
108+
#endif /* __IASMARM__ */
109+
#define xPortPendSVHandler PendSV_Handler
110+
#define vPortSVCHandler SVC_Handler
111+
#define xPortSysTickHandler SysTick_Handler
112+
#endif /* FREERTOS_CONFIG_H */

apps/microtvm/ethosu/include/tvm_runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ TVM_DLL int TVMFuncRegisterGlobal(const char* name, TVMFunctionHandle f, int ove
5757

5858
#ifdef __cplusplus
5959
}
60-
#endif
60+
#endif

apps/microtvm/ethosu/run_demo.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ while (( $# )); do
7171
fi
7272
;;
7373

74+
--freertos_path)
75+
if [ $# -gt 1 ]
76+
then
77+
export FREERTOS_PATH="$2"
78+
shift 2
79+
else
80+
echo 'ERROR: --freertos_path requires a non-empty argument' >&2
81+
show_usage >&2
82+
exit 1
83+
fi
84+
;;
85+
7486
--ethosu_platform_path)
7587
if [ $# -gt 1 ]
7688
then
@@ -105,7 +117,7 @@ while (( $# )); do
105117
show_usage >&2
106118
exit 1
107119
fi
108-
;;
120+
;;
109121

110122
-*|--*)
111123
echo "Error: Unknown flag: $1" >&2
File renamed without changes.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include <FreeRTOS.h>
21+
#include <queue.h>
22+
#include <stdio.h>
23+
#include <task.h>
24+
#include <tvm_runtime.h>
25+
26+
#include "ethosu_mod.h"
27+
#include "uart.h"
28+
29+
// Header files generated by convert_image.py and convert_labels.py
30+
#include "inputs.h"
31+
#include "labels.h"
32+
#include "outputs.h"
33+
34+
static void prvInferenceTask(void* pvParameters);
35+
static void prvDataCollectionTask(void* pvParameters);
36+
37+
#define mainQUEUE_INFERENCE_TASK_PRIORITY (tskIDLE_PRIORITY + 3)
38+
#define mainQUEUE_INFERENCE_TASK_STACK_SIZE 4096
39+
#define mainQUEUE_DATA_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
40+
#define mainQUEUE_DATA_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
41+
#define mainQUEUE_LENGTH (1)
42+
#define mainQUEUE_SEND_FREQUENCY_MS (100 / portTICK_PERIOD_MS)
43+
44+
/* The queue used to pass data to run through our model */
45+
static QueueHandle_t xQueue = NULL;
46+
47+
int main(void) {
48+
// Platform UART
49+
uart_init();
50+
// NPU
51+
EthosuInit();
52+
// TVM Memory Manager
53+
StackMemoryManager_Init(&app_workspace, g_aot_memory, WORKSPACE_SIZE);
54+
55+
// Queue for inferences
56+
xQueue = xQueueCreate(mainQUEUE_LENGTH, sizeof(uint8_t*));
57+
58+
if (xQueue != NULL) {
59+
// Inference task
60+
xTaskCreate(prvInferenceTask, "Inference", mainQUEUE_INFERENCE_TASK_STACK_SIZE, NULL,
61+
mainQUEUE_INFERENCE_TASK_PRIORITY, NULL);
62+
63+
// Data collector task
64+
xTaskCreate(prvDataCollectionTask, "Data", mainQUEUE_DATA_TASK_STACK_SIZE, NULL,
65+
mainQUEUE_DATA_TASK_PRIORITY, NULL);
66+
67+
// Start the task scheduling
68+
vTaskStartScheduler();
69+
}
70+
71+
// The task scheduler should take over before this is reached
72+
printf("Unreachable code reached!\n");
73+
}
74+
75+
/*
76+
* This task emulates collection of data and sending it to another inference task
77+
* for processing
78+
*/
79+
static void prvDataCollectionTask(void* pvParameters) {
80+
// Unused
81+
(void)pvParameters;
82+
83+
// Working
84+
vTaskDelay(mainQUEUE_SEND_FREQUENCY_MS);
85+
86+
// Construct pointer to copy to queue
87+
uint8_t** pucInputData = &input;
88+
xQueueSend(xQueue, &pucInputData, 0U);
89+
}
90+
91+
/*
92+
* This task emulates the inference of data sent by the collector task
93+
*/
94+
static void prvInferenceTask(void* pvParameters) {
95+
uint8_t* pucReceivedData;
96+
97+
// Unused
98+
(void)pvParameters;
99+
100+
// Wait for data collection
101+
xQueueReceive(xQueue, &pucReceivedData, portMAX_DELAY);
102+
103+
// Print output of inference and exit task
104+
printf("Running inference\n");
105+
struct tvmgen_default_inputs xInputs = {
106+
.tfl_quantize = pucReceivedData,
107+
};
108+
struct tvmgen_default_outputs xOutputs = {
109+
.output = output,
110+
};
111+
struct ethosu_driver* xDriver = ethosu_reserve_driver();
112+
struct tvmgen_default_devices xDevices = {
113+
.ethos_u = xDriver,
114+
};
115+
tvmgen_default_run(&xInputs, &xOutputs, &xDevices);
116+
ethosu_release_driver(xDriver);
117+
118+
// Calculate index of max value
119+
int8_t ucMaxValue = -128;
120+
int32_t lMaxIndex = -1;
121+
for (unsigned int i = 0; i < output_len; ++i) {
122+
if (output[i] > ucMaxValue) {
123+
ucMaxValue = output[i];
124+
lMaxIndex = i;
125+
}
126+
}
127+
printf("The image has been classified as '%s'\n", labels[lMaxIndex]);
128+
129+
// The FVP will shut down when it receives "EXITTHESIM" on the UART
130+
printf("EXITTHESIM\n");
131+
}

apps/microtvm/zephyr_cmsisnn/run_demo.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export ARMFVP_BIN_PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4/
4545
west zephyr-export
4646
west build
4747
west build -t run &> ${LOGDIR}/west.log &
48-
WEST_PID=$!
4948

5049
# Wait for "exit" keyword
5150
until grep -m 1 "exit" ${LOGDIR}/west.log; do sleep 1 ; done

gallery/how_to/work_with_microtvm/micro_ethosu.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@
411411
#
412412
# `include files <https://github.com/apache/tvm/tree/main/apps/microtvm/ethosu/include>`_
413413

414+
################################################################################
415+
# .. note::
416+
#
417+
# If you'd like to use FreeRTOS for task scheduling and queues, a sample application can be found here
418+
# `demo_freertos.c <https://github.com/apache/tvm/blob/main/apps/microtvm/ethosu/src/demo_freertos.c>`
419+
414420
################################################################################
415421
# Creating the linker script
416422
# --------------------------
@@ -453,6 +459,13 @@
453459
# An example Makefile can be found here:
454460
# `Makefile <https://github.com/apache/tvm/blob/main/apps/microtvm/ethosu/Makefile>`_
455461

462+
################################################################################
463+
# .. note::
464+
#
465+
# If you're using FreeRTOS, the Makefile builds it from the specified FREERTOS_PATH:
466+
# ``make FREERTOS_PATH=<FreeRTOS directory>``
467+
#
468+
456469
################################################################################
457470
# Running the demo application
458471
# ----------------------------

0 commit comments

Comments
 (0)