ソースを参照

gcov: add gcov callback into the ipc task

Erhan Kurubas 4 年 前
コミット
886ea8d33b

+ 1 - 1
components/app_trace/CMakeLists.txt

@@ -30,7 +30,7 @@ endif()
 
 idf_component_register(SRCS "${srcs}"
                        INCLUDE_DIRS "${include_dirs}"
-                       PRIV_REQUIRES soc
+                       PRIV_REQUIRES soc esp_ipc
                        LDFRAGMENTS linker.lf)
 
 

+ 21 - 5
components/app_trace/gcov/gcov_rtio.c

@@ -24,6 +24,7 @@
 #include "esp_app_trace.h"
 #include "esp_freertos_hooks.h"
 #include "esp_private/dbg_stubs.h"
+#include "esp_ipc.h"
 #include "hal/wdt_hal.h"
 #if CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/libc_stubs.h"
@@ -49,6 +50,8 @@ void gcov_dump_task(void *pvParameter)
     int dump_result = 0;
     bool *running = (bool *)pvParameter;
 
+    ESP_EARLY_LOGV(TAG, "%s stack use in %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
+
     ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE);
     void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE);
     if (down_buf == NULL) {
@@ -81,14 +84,25 @@ gcov_exit:
     if (running) {
         *running = false;
     }
+
+    ESP_EARLY_LOGV(TAG, "%s stack use out %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
+
     vTaskDelete(NULL);
 }
 
-static void gcov_create_task_hook(void)
+void gcov_create_task(void *arg)
 {
+    ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
+    xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", 2048, (void *)&s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0);
+}
+
+void gcov_create_task_tick_hook(void)
+{
+    extern esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
     if (s_create_gcov_task) {
-        xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", 2048, &s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0);
-        s_create_gcov_task = false;
+        if (esp_ipc_start_gcov_from_isr(xPortGetCoreID(), &gcov_create_task, NULL) == ESP_OK) {
+            s_create_gcov_task = false;
+        }
     }
 }
 
@@ -114,19 +128,21 @@ int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
     if (esp_dbg_stub_entry_get(ESP_DBG_STUB_CAPABILITIES, &capabilities) == ESP_OK) {
         esp_dbg_stub_entry_set(ESP_DBG_STUB_CAPABILITIES, capabilities | ESP_DBG_STUB_CAP_GCOV_TASK);
     }
-    esp_register_freertos_tick_hook(gcov_create_task_hook);
+    esp_register_freertos_tick_hook(gcov_create_task_tick_hook);
     return ESP_OK;
 }
 
 void esp_gcov_dump(void)
 {
+    ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
+
     while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
         vTaskDelay(pdMS_TO_TICKS(10));
     }
 
     /* We are not in isr context here. Waiting for the completion is safe */
-    s_create_gcov_task = true;
     s_gcov_task_running = true;
+    s_create_gcov_task = true;
     while (s_gcov_task_running) {
         vTaskDelay(pdMS_TO_TICKS(10));
     }

+ 1 - 0
components/esp_common/src/dbg_stubs.c

@@ -82,6 +82,7 @@ void esp_dbg_stubs_init(void)
     ESP_LOGV(TAG, "%s stubs %x", __func__, eri_read(ESP_DBG_STUBS_TRAX_REG));
 }
 
+// TODO: add lock mechanism. Not now but in the future ESP_DBG_STUB_CAPABILITIES can be set from different places.
 esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry)
 {
     if (id < ESP_DBG_STUB_ENTRY_FIRST || id >= ESP_DBG_STUB_ENTRY_MAX) {

+ 39 - 9
components/esp_ipc/ipc.c

@@ -28,7 +28,7 @@ static TaskHandle_t s_ipc_task_handle[portNUM_PROCESSORS];
 static SemaphoreHandle_t s_ipc_mutex[portNUM_PROCESSORS];    // This mutex is used as a global lock for esp_ipc_* APIs
 static SemaphoreHandle_t s_ipc_sem[portNUM_PROCESSORS];      // Two semaphores used to wake each of ipc tasks
 static SemaphoreHandle_t s_ipc_ack[portNUM_PROCESSORS];      // Semaphore used to acknowledge that task was woken up,
-                                                             //   or function has finished running
+                                                             // or function has finished running
 static volatile esp_ipc_func_t s_func[portNUM_PROCESSORS];   // Function which should be called by high priority task
 static void * volatile s_func_arg[portNUM_PROCESSORS];       // Argument to pass into s_func
 typedef enum {
@@ -40,6 +40,11 @@ static volatile esp_ipc_wait_t s_ipc_wait[portNUM_PROCESSORS];// This variable t
                                                              //   s_ipc_ack semaphore: before s_func is called, or
                                                              //   after it returns
 
+#if CONFIG_APPTRACE_GCOV_ENABLE
+static volatile esp_ipc_func_t s_gcov_func = NULL;           // Gcov dump starter function which should be called by high priority task
+static void * volatile s_gcov_func_arg;                      // Argument to pass into s_gcov_func
+#endif
+
 static void IRAM_ATTR ipc_task(void* arg)
 {
     const uint32_t cpuid = (uint32_t) arg;
@@ -53,16 +58,26 @@ static void IRAM_ATTR ipc_task(void* arg)
             abort();
         }
 
-        esp_ipc_func_t func = s_func[cpuid];
-        void* arg = s_func_arg[cpuid];
-
-        if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_START) {
-            xSemaphoreGive(s_ipc_ack[cpuid]);
+#if CONFIG_APPTRACE_GCOV_ENABLE
+        if (s_gcov_func) {
+            (*s_gcov_func)(s_gcov_func_arg);
+            s_gcov_func = NULL;
         }
-        (*func)(arg);
-        if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_END) {
-            xSemaphoreGive(s_ipc_ack[cpuid]);
+#endif
+        if (s_func[cpuid]) {
+            esp_ipc_func_t func = s_func[cpuid];
+            void* arg = s_func_arg[cpuid];
+
+            if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_START) {
+                xSemaphoreGive(s_ipc_ack[cpuid]);
+            }
+            (*func)(arg);
+            if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_END) {
+                xSemaphoreGive(s_ipc_ack[cpuid]);
+            }
+            s_func[cpuid] = NULL;
         }
+
     }
     // TODO: currently this is unreachable code. Introduce esp_ipc_uninit
     // function which will signal to both tasks that they can shut down.
@@ -87,6 +102,7 @@ static void esp_ipc_init(void) __attribute__((constructor));
 static void esp_ipc_init(void)
 {
     char task_name[15];
+
     for (int i = 0; i < portNUM_PROCESSORS; ++i) {
         snprintf(task_name, sizeof(task_name), "ipc%d", i);
         s_ipc_mutex[i] = xSemaphoreCreateMutex();
@@ -144,3 +160,17 @@ esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg)
     return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_END);
 }
 
+// currently this is only called from gcov component
+#if CONFIG_APPTRACE_GCOV_ENABLE
+esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void* arg)
+{
+    if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    s_gcov_func = func;
+    s_gcov_func_arg = arg;
+    xSemaphoreGiveFromISR(s_ipc_sem[cpu_id], NULL);
+
+    return ESP_OK;
+}
+#endif