aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Moberg <anton.moberg@arm.com>2021-02-02 11:26:48 +0100
committerAnton Moberg <anton.moberg@arm.com>2021-02-19 10:53:57 +0100
commitdf386e00295e32e05b9a76758ca5767b4d021848 (patch)
tree94416af2d1bf1141a96ff13f715ebd6436c8059c
parent61da4d35575ddf7f62d4f5c687356f65a7246aed (diff)
downloadethos-u-core-driver-df386e00295e32e05b9a76758ca5767b4d021848.tar.gz
MLBEDSW-3868 - Driver multiNPU locking
Added: Weak linked symbols for locking if RTOS overrides Added: Semaphore Producer (release a reserved driver) Added: Semaphore Consumer (all drivers reserved and waiting for returned driver) Added: Mutex protect thread sensitive driver access Added: Weak linked symbols for yielding & resuming thread/task while waiting for IRQ Added: static inline function of ethosu_invoke_v2(...) for backwards compatibility Change-Id: If415a73b01b2357b31bb6da86f3038344c4245c6
-rw-r--r--include/ethosu_driver.h19
-rw-r--r--src/ethosu_driver.c72
2 files changed, 87 insertions, 4 deletions
diff --git a/include/ethosu_driver.h b/include/ethosu_driver.h
index 70e3110..2ce59c2 100644
--- a/include/ethosu_driver.h
+++ b/include/ethosu_driver.h
@@ -124,8 +124,6 @@ int ethosu_invoke_v3(struct ethosu_driver *drv,
#define ethosu_invoke(custom_data_ptr, custom_data_size, base_addr, num_base_addr) \
ethosu_invoke_v2(custom_data_ptr, custom_data_size, base_addr, NULL, num_base_addr)
-#define ethosu_invoke_v2(custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr) \
- ethosu_invoke_v3(&ethosu_drv, custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr)
/**
* Abort Ethos-U inference.
@@ -159,7 +157,7 @@ int ethosu_register_driver(struct ethosu_driver *drv);
int ethosu_deregister_driver(struct ethosu_driver *drv);
/**
- * Find, reserve, and return the first available driver
+ * Reserves a driver to execute inference with
*/
struct ethosu_driver *ethosu_reserve_driver(void);
@@ -168,6 +166,21 @@ struct ethosu_driver *ethosu_reserve_driver(void);
*/
void ethosu_release_driver(struct ethosu_driver *drv);
+/**
+ * Static inline for backwards-compatibility
+ */
+static inline int ethosu_invoke_v2(const void *custom_data_ptr,
+ const int custom_data_size,
+ const uint64_t *base_addr,
+ const size_t *base_addr_size,
+ const int num_base_addr)
+{
+ struct ethosu_driver *drv = ethosu_reserve_driver();
+ int result = ethosu_invoke_v3(drv, custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr);
+ ethosu_release_driver(drv);
+ return result;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c
index 2eedfe3..cb1790e 100644
--- a/src/ethosu_driver.c
+++ b/src/ethosu_driver.c
@@ -161,6 +161,46 @@ static struct ethosu_driver *registered_drivers = NULL;
static volatile bool irq_triggered = false;
static int ethosu_soft_reset_and_restore(struct ethosu_driver *drv);
+/* Default implementation to initialise ethosu driver mutex. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_mutex_init() {}
+
+/* Default implementation to initialise ethosu driver binary semaphore. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_semaphore_init() {}
+
+/* Default implementation to lock ethosu driver mutex. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_mutex_lock() {}
+
+/* Default implementation to unlock ethosu driver mutex. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_mutex_unlock() {}
+
+/* Default implementation to wait for and take free ethosu driver semaphore. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_semaphore_take() {}
+
+/* Default implementation to give ethosu driver semaphore. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_semaphore_give() {}
+
+/* Default implementation to force context-switch while waiting for Ethos-U IRQ. Override if available on the targeted
+ * RTOS. If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_yield() {}
+
+/* Default implementation to indicate thread/task is resuming. Override if available on the targeted RTOS.
+ * If not overridden, will do nothing (assumes baremetal).
+ */
+void __attribute__((weak)) ethosu_resume() {}
+
void ethosu_irq_handler_v2(struct ethosu_driver *drv)
{
uint8_t irq_raised = 0;
@@ -201,7 +241,9 @@ static inline void wait_for_irq(struct ethosu_driver *drv)
__WFI();
+ ethosu_yield();
__enable_irq();
+ ethosu_resume();
}
}
@@ -217,6 +259,7 @@ static int dump_shram(struct ethosu_driver *drv);
static void dump_npu_register(struct ethosu_driver *drv, int npu_reg, int npu_reg_end);
static void dump_command_stream(const uint32_t *cmd_stream, const int cms_length, int qread);
static void npu_axi_init(struct ethosu_driver *drv);
+static struct ethosu_driver *ethosu_find_and_reserve_driver(void);
int ethosu_init_v4(struct ethosu_driver *drv,
const void *base_address,
@@ -235,6 +278,8 @@ int ethosu_init_v4(struct ethosu_driver *drv,
secure_enable,
privilege_enable);
+ ethosu_mutex_init();
+ ethosu_semaphore_init();
ethosu_register_driver(drv);
drv->fast_memory = (uint32_t)fast_memory;
@@ -470,7 +515,6 @@ int ethosu_register_driver(struct ethosu_driver *drv)
registered_drivers = drv;
LOG_INFO("%s: New NPU driver at address %p is registered.\n", __FUNCTION__, drv);
-
return 0;
}
@@ -495,11 +539,34 @@ int ethosu_deregister_driver(struct ethosu_driver *drv)
LOG_ERR("%s: NPU driver at address %p does not match a registered driver and therefore may not be deregistered.\n",
__FUNCTION__,
drv);
+
return -1;
}
struct ethosu_driver *ethosu_reserve_driver(void)
{
+ struct ethosu_driver *drv = NULL;
+
+ do
+ {
+ ethosu_mutex_lock();
+ drv = ethosu_find_and_reserve_driver();
+ ethosu_mutex_unlock();
+
+ if (drv != NULL)
+ {
+ break;
+ }
+
+ ethosu_semaphore_take();
+
+ } while (1);
+
+ return drv;
+}
+
+static struct ethosu_driver *ethosu_find_and_reserve_driver(void)
+{
struct ethosu_driver *drv = registered_drivers;
while (drv != NULL)
@@ -520,11 +587,14 @@ struct ethosu_driver *ethosu_reserve_driver(void)
void ethosu_release_driver(struct ethosu_driver *drv)
{
+ ethosu_mutex_lock();
if (drv != NULL && drv->reserved)
{
drv->reserved = false;
LOG_INFO("%s - Driver %p released\n", __FUNCTION__, drv);
+ ethosu_semaphore_give();
}
+ ethosu_mutex_unlock();
}
static int ethosu_soft_reset_and_restore(struct ethosu_driver *drv)