Add ethosu_monitor example to baremetal application.

Change-Id: Ided3ff5e2a5fc1f16e2fad0732f5464ccddbc96c
diff --git a/applications/CMakeLists.txt b/applications/CMakeLists.txt
index 154b599..a0442c8 100644
--- a/applications/CMakeLists.txt
+++ b/applications/CMakeLists.txt
@@ -27,4 +27,4 @@
 if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang")
     # Only armclang supported for now
     add_subdirectory(trustzone_inference)
-endif()
\ No newline at end of file
+endif()
diff --git a/applications/baremetal/CMakeLists.txt b/applications/baremetal/CMakeLists.txt
index c9d965b..9128e8a 100644
--- a/applications/baremetal/CMakeLists.txt
+++ b/applications/baremetal/CMakeLists.txt
@@ -25,13 +25,16 @@
 endif()
 
 ethosu_add_executable_test(baremetal_keyword_cnn PRIVATE
-    SOURCES main.cpp)
+    SOURCES main.cpp
+    LIBRARIES ethosu_monitor)
 target_include_directories(baremetal_keyword_cnn PRIVATE models/keyword_spotting_cnn_small_int8)
 
 ethosu_add_executable_test(baremetal_keyword_dnn PRIVATE
-    SOURCES main.cpp)
+    SOURCES main.cpp
+    LIBRARIES ethosu_monitor)
 target_include_directories(baremetal_keyword_dnn PRIVATE models/keyword_spotting_dnn_medium_int8)
 
 ethosu_add_executable_test(baremetal_keyword_ds_dnn PRIVATE
-    SOURCES main.cpp)
+    SOURCES main.cpp
+    LIBRARIES ethosu_monitor)
 target_include_directories(baremetal_keyword_ds_dnn PRIVATE models/keyword_spotting_ds_dnn_large_clustered_int8)
diff --git a/applications/baremetal/main.cpp b/applications/baremetal/main.cpp
index 4c0bf50..0c89058 100644
--- a/applications/baremetal/main.cpp
+++ b/applications/baremetal/main.cpp
@@ -33,6 +33,11 @@
 #include "model.h"
 #include "output.h"
 
+#ifdef ETHOSU
+#include <ethosu_monitor.hpp>
+#include <pmu_ethosu.h>
+#endif
+
 using namespace std;
 
 /****************************************************************************
@@ -49,6 +54,39 @@
 
 uint8_t outputData[sizeof(expectedOutputData)] __attribute__((aligned(16), section("output_data_sec")));
 
+#ifdef ETHOSU
+namespace {
+std::vector<ethosu_pmu_event_type> pmuEventConfig{ETHOSU_PMU_CYCLE, ETHOSU_PMU_NPU_ACTIVE};
+const uint32_t delayMs = SystemCoreClock / 60ul;
+struct ethosu_driver *ethosuDrv;
+EthosUMonitor ethosuMonitor(0, EthosUMonitor::Backend::EVENT_RECORDER);
+} // namespace
+
+extern "C" {
+
+void SysTick_Handler(void) {
+    ethosuMonitor.monitorSample(ethosuDrv);
+}
+
+void ethosu_inference_begin(struct ethosu_driver *drv, const void *) {
+    ethosuDrv = drv;
+    ethosuMonitor.configure(drv, pmuEventConfig);
+
+    // Enable polling
+    SysTick_Config(delayMs);
+}
+
+void ethosu_inference_end(struct ethosu_driver *drv, const void *) {
+    // Disable polling
+    SysTick->CTRL = 0;
+
+    ethosuDrv = 0;
+    ethosuMonitor.monitorSample(drv);
+    ethosuMonitor.release(drv);
+}
+}
+#endif
+
 int runInference() {
     // Load inference data
     vector<InferenceProcess::DataPtr> input;
@@ -79,6 +117,9 @@
 }
 
 int main() {
+#ifdef ETHOSU
+    EventRecorderInitialize(EventRecordAll, 1);
+#endif
     int ret = runInference();
     return ret;
 }