blob: d478ae6c06058463f1543bc6f063e6de7a693e3a [file] [log] [blame]
Yulia Garbovichf61ea352021-11-11 14:16:57 +02001/*
Kristofer Jonssonac535f02022-03-10 11:08:39 +01002 * Copyright (c) 2019-2022 Arm Limited.
Yulia Garbovichf61ea352021-11-11 14:16:57 +02003 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/****************************************************************************
20 * Includes
21 ****************************************************************************/
22
23#include "FreeRTOS.h"
24#include "queue.h"
25#include "semphr.h"
26#include "task.h"
27
28#include <inttypes.h>
29#include <stdio.h>
30
31#include "ethosu_core_interface.h"
32#include "message_handler.hpp"
33#include "message_queue.hpp"
34#include <mailbox.hpp>
35
36#if defined(MHU_V2)
37#include <mhu_v2.hpp>
38#elif defined(MHU_JUNO)
39#include <mhu_juno.hpp>
40#else
41#include <mhu_dummy.hpp>
42#endif
43
44/* Disable semihosting */
45__asm(".global __use_no_semihosting\n\t");
46
47using namespace EthosU;
48using namespace MessageHandler;
49
50/****************************************************************************
51 * Defines
52 ****************************************************************************/
53
54// Nr. of tasks to process inferences with, reserves driver & runs inference (Normally 1 per NPU, but not a must)
55#if defined(ETHOSU_NPU_COUNT)
56constexpr size_t NUM_PARALLEL_TASKS = ETHOSU_NPU_COUNT;
57#else
58constexpr size_t NUM_PARALLEL_TASKS = 1;
59#endif
60
61// TensorArena static initialisation
62constexpr size_t arenaSize = TENSOR_ARENA_SIZE / NUM_PARALLEL_TASKS;
63
64__attribute__((section(".bss.tensor_arena"), aligned(16))) uint8_t tensorArena[NUM_PARALLEL_TASKS][arenaSize];
65
66// Message queue from remote host
67__attribute__((section("ethosu_core_in_queue"))) MessageQueue::Queue<1000> inputMessageQueue;
68
69// Message queue to remote host
70__attribute__((section("ethosu_core_out_queue"))) MessageQueue::Queue<1000> outputMessageQueue;
71
72namespace {
Yulia Garbovichf61ea352021-11-11 14:16:57 +020073
Davide Grohmann134c39e2022-04-25 12:21:12 +020074SemaphoreHandle_t messageNotify;
75QueueHandle_t inferenceInputQueue;
76QueueHandle_t inferenceOutputQueue;
Yulia Garbovichf61ea352021-11-11 14:16:57 +020077
78// Mailbox driver
79#ifdef MHU_V2
80Mailbox::MHUv2 mailbox(MHU_TX_BASE_ADDRESS, MHU_RX_BASE_ADDRESS); // txBase, rxBase
81#elif defined(MHU_JUNO)
82Mailbox::MHUJuno mailbox(MHU_BASE_ADDRESS);
83#else
84Mailbox::MHUDummy mailbox;
85#endif
86
87} // namespace
88
89/****************************************************************************
90 * Mutex & Semaphore
91 ****************************************************************************/
92
93extern "C" {
94
95void *ethosu_mutex_create(void) {
96 return xSemaphoreCreateMutex();
97}
98
99void ethosu_mutex_lock(void *mutex) {
100 SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
101 xSemaphoreTake(handle, portMAX_DELAY);
102}
103
104void ethosu_mutex_unlock(void *mutex) {
105 SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(mutex);
106 xSemaphoreGive(handle);
107}
108
109void *ethosu_semaphore_create(void) {
110 return xSemaphoreCreateBinary();
111}
112
113void ethosu_semaphore_take(void *sem) {
114 SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
115 xSemaphoreTake(handle, portMAX_DELAY);
116}
117
118void ethosu_semaphore_give(void *sem) {
119 SemaphoreHandle_t handle = reinterpret_cast<SemaphoreHandle_t>(sem);
120 xSemaphoreGiveFromISR(handle, NULL);
121}
122}
123
124/****************************************************************************
125 * Application
126 ****************************************************************************/
127
128namespace {
129
Kristofer Jonsson29467e02021-11-26 16:10:43 +0100130#ifdef MHU_IRQ
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200131void mailboxIrqHandler() {
132 mailbox.handleMessage();
133}
Kristofer Jonsson29467e02021-11-26 16:10:43 +0100134#endif
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200135
136void inferenceTask(void *pvParameters) {
137 printf("Starting inference task\n");
138
139 uint8_t *arena = reinterpret_cast<uint8_t *>(pvParameters);
Davide Grohmann134c39e2022-04-25 12:21:12 +0200140 InferenceHandler process(arena, arenaSize, inferenceInputQueue, inferenceOutputQueue, messageNotify);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200141 process.run();
142}
143
Davide Grohmann134c39e2022-04-25 12:21:12 +0200144void messageTask(void *) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200145 printf("Starting input message task\n");
146
Davide Grohmann134c39e2022-04-25 12:21:12 +0200147 IncomingMessageHandler process(*inputMessageQueue.toQueue(),
148 *outputMessageQueue.toQueue(),
149 mailbox,
150 inferenceInputQueue,
151 inferenceOutputQueue,
152 messageNotify);
Kristofer Jonssond89ee0d2022-04-01 15:41:06 +0200153
154#ifdef MHU_IRQ
155 // Register mailbox interrupt handler
156 NVIC_SetVector((IRQn_Type)MHU_IRQ, (uint32_t)&mailboxIrqHandler);
157 NVIC_EnableIRQ((IRQn_Type)MHU_IRQ);
158#endif
159
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200160 process.run();
161}
162
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200163} // namespace
164
165// FreeRTOS application. NOTE: Additional tasks may require increased heap size.
166int main() {
167 BaseType_t ret;
168
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200169 if (!mailbox.verifyHardware()) {
170 printf("Failed to verify mailbox hardware\n");
171 return 1;
172 }
173
174 // Create message queues for inter process communication
Davide Grohmann134c39e2022-04-25 12:21:12 +0200175 messageNotify = xSemaphoreCreateBinary();
176 inferenceInputQueue = xQueueCreate(10, sizeof(ethosu_core_inference_req));
177 inferenceOutputQueue = xQueueCreate(10, sizeof(ethosu_core_inference_rsp));
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200178
179 // Task for handling incoming messages from the remote host
Davide Grohmann134c39e2022-04-25 12:21:12 +0200180 ret = xTaskCreate(messageTask, "messageTask", 1024, nullptr, 2, nullptr);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200181 if (ret != pdPASS) {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200182 printf("Failed to create 'messageTask'\n");
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200183 return ret;
184 }
185
186 // One inference task for each NPU
187 for (size_t n = 0; n < NUM_PARALLEL_TASKS; n++) {
188 ret = xTaskCreate(inferenceTask, "inferenceTask", 8 * 1024, &tensorArena[n], 3, nullptr);
189 if (ret != pdPASS) {
190 printf("Failed to create 'inferenceTask%d'\n", n);
191 return ret;
192 }
193 }
194
195 // Start Scheduler
196 vTaskStartScheduler();
197
198 return 1;
199}