mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
gcov: add gcov callback into the ipc task
This commit is contained in:
parent
49942a9468
commit
fd8b943619
@ -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)
|
||||
|
||||
|
||||
|
@ -24,7 +24,8 @@
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#include "esp_ipc.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/libc_stubs.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
@ -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));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 CONFIG_APPTRACE_GCOV_ENABLE
|
||||
if (s_gcov_func) {
|
||||
(*s_gcov_func)(s_gcov_func_arg);
|
||||
s_gcov_func = NULL;
|
||||
}
|
||||
#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]);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user