diff --git a/test_apps/build_apps.py b/test_apps/build_apps.py index 9b8b842..aca83be 100644 --- a/test_apps/build_apps.py +++ b/test_apps/build_apps.py @@ -25,6 +25,8 @@ IGNORE_WARNINGS = [ r'pkg_resources is deprecated as an API', r'the value \'y\' is invalid for SOC_PCNT_GROUPS', r'\'1\' is not a valid value for the bool symbol SOC_PCNT_GROUPS', + r'\'task_stack\' defined but not used', + r'\'task_state\' defined but not used', ] def _get_idf_version(): diff --git a/test_apps/esp-sr/main/CMakeLists.txt b/test_apps/esp-sr/main/CMakeLists.txt index 4248c61..d67a859 100644 --- a/test_apps/esp-sr/main/CMakeLists.txt +++ b/test_apps/esp-sr/main/CMakeLists.txt @@ -12,5 +12,5 @@ idf_component_register(SRCS ${srcs} REQUIRES unity esp-sr WHOLE_ARCHIVE) - +target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") endif() diff --git a/test_apps/esp-sr/main/test_afe.c b/test_apps/esp-sr/main/test_afe.c index 58394dc..dcb29b6 100644 --- a/test_apps/esp-sr/main/test_afe.c +++ b/test_apps/esp-sr/main/test_afe.c @@ -20,10 +20,32 @@ #include "dl_lib_convq_queue.h" #include +#define ARRAY_SIZE_OFFSET 8 // Increase this if audio_sys_get_real_time_stats returns ESP_ERR_INVALID_SIZE +#define AUDIO_SYS_TASKS_ELAPSED_TIME_MS 1000 // Period of stats measurement + +static const char *TAG = "AFE_TEST"; +static volatile int s_cpu_test_task_flag = 0; static esp_afe_sr_data_t *afe_data = NULL; +static int total_ram_size_before = 0; +static int internal_ram_size_before = 0; +static int psram_size_before = 0; -TEST_CASE("audio_front_end SR create/destroy API & memory leak", "[afe]") +const static char *task_state[] = { + "Running", + "Ready", + "Blocked", + "Suspended", + "Deleted" +}; + +/** @brief +* "Extr": Allocated task stack from psram, "Intr": Allocated task stack from internel +*/ +const static char *task_stack[] = {"Extr", "Intr"}; + + +TEST_CASE(">>>>>>>> audio_front_end SR create/destroy API & memory leak <<<<<<<<", "[afe]") { int audio_chunksize = 0; int16_t *feed_buff = NULL; @@ -107,13 +129,224 @@ TEST_CASE("audio_front_end SR create/destroy API & memory leak", "[afe]") } } +void test_feed_Task(void *arg) +{ + int sample_per_ms = 16; + // esp_afe_sr_iface_t *afe_handle = &ESP_AFE_SR_HANDLE; + esp_afe_sr_iface_t *afe_handle = (esp_afe_sr_iface_t *)arg; + int feed_chunksize = afe_handle->get_feed_chunksize(afe_data); + int total_nch = afe_handle->get_total_channel_num(afe_data); + int16_t *i2s_buff = malloc(feed_chunksize * sizeof(int16_t) * total_nch); + assert(i2s_buff); + ESP_LOGI(TAG, "feed task start\n"); + // FILE *fp = fopen("/sdcard/out", "w"); + // if (fp == NULL) printf("can not open file\n"); + + while (s_cpu_test_task_flag) { + // FatfsComboWrite(i2s_buff, audio_chunksize * I2S_CHANNEL_NUM * sizeof(int16_t), 1, fp); + + afe_handle->feed(afe_data, i2s_buff); + vTaskDelay((feed_chunksize / sample_per_ms) / portTICK_PERIOD_MS); + } + if (i2s_buff) { + free(i2s_buff); + } + ESP_LOGI(TAG, "feed task quit\n"); + vTaskDelete(NULL); +} + +void test_detect_Task(void *arg) +{ + // esp_afe_sr_iface_t *afe_handle = &ESP_AFE_SR_HANDLE; + esp_afe_sr_iface_t *afe_handle = (esp_afe_sr_iface_t *)arg; + int fetch_chunksize = afe_handle->get_fetch_chunksize(afe_data); + int16_t *buff = malloc(fetch_chunksize * sizeof(int16_t)); + assert(buff); + ESP_LOGI(TAG, "------------detect start------------\n"); + + // FILE *fp = fopen("/sdcard/out1", "w"); + // if (fp == NULL) printf("can not open file\n"); + + while (s_cpu_test_task_flag) { + afe_fetch_result_t* res = afe_handle->fetch(afe_data); + if (!res || res->ret_value == ESP_FAIL) { + printf("fetch error!\n"); + break; + } + + if (res->wakeup_state == WAKENET_DETECTED) { + ESP_LOGI(TAG, "wakeword detected\n"); + } + if (res->wakeup_state == WAKENET_CHANNEL_VERIFIED) { + ESP_LOGI(TAG, "AFE_FETCH_CHANNEL_VERIFIED\n"); + } + } + if (buff) { + free(buff); + } + ESP_LOGI(TAG, "detect task quit\n"); + vTaskDelete(NULL); +} + +esp_err_t audio_sys_get_real_time_stats(void) +{ +#if (CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID && CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS) + TaskStatus_t *start_array = NULL, *end_array = NULL; + UBaseType_t start_array_size, end_array_size; + uint32_t start_run_time, end_run_time; + uint32_t task_elapsed_time, percentage_time; + esp_err_t ret; + + // Allocate array to store current task states + start_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET; + start_array = malloc(sizeof(TaskStatus_t) * start_array_size); + assert(start_array); + // Get current task states + start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time); + if (start_array_size == 0) { + ESP_LOGE(TAG, "Insufficient array size for uxTaskGetSystemState. Trying increasing ARRAY_SIZE_OFFSET"); + ret = ESP_FAIL; + goto exit; + } + + vTaskDelay(pdMS_TO_TICKS(AUDIO_SYS_TASKS_ELAPSED_TIME_MS)); + + // Allocate array to store tasks states post delay + end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET; + end_array = malloc(sizeof(TaskStatus_t) * end_array_size); + assert(end_array); + + // Get post delay task states + end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time); + if (end_array_size == 0) { + ESP_LOGE(TAG, "Insufficient array size for uxTaskGetSystemState. Trying increasing ARRAY_SIZE_OFFSET"); + ret = ESP_FAIL; + goto exit; + } + + // Calculate total_elapsed_time in units of run time stats clock period. + uint32_t total_elapsed_time = (end_run_time - start_run_time); + if (total_elapsed_time == 0) { + ESP_LOGE(TAG, "Delay duration too short. Trying increasing AUDIO_SYS_TASKS_ELAPSED_TIME_MS"); + ret = ESP_FAIL; + goto exit; + } + + ESP_LOGI(TAG, "| Task | Run Time | Per | Prio | HWM | State | CoreId | Stack "); + + // Match each task in start_array to those in the end_array + for (int i = 0; i < start_array_size; i++) { + for (int j = 0; j < end_array_size; j++) { + if (start_array[i].xHandle == end_array[j].xHandle) { + + task_elapsed_time = end_array[j].ulRunTimeCounter - start_array[i].ulRunTimeCounter; + percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * portNUM_PROCESSORS); + ESP_LOGI(TAG, "| %-17s | %-11d |%2d%% | %-4u | %-9u | %-7s | %-8x | %s", + start_array[i].pcTaskName, task_elapsed_time, percentage_time, start_array[i].uxCurrentPriority, + start_array[i].usStackHighWaterMark, task_state[(start_array[i].eCurrentState)], + start_array[i].xCoreID, task_stack[esp_ptr_internal(pxTaskGetStackStart(start_array[i].xHandle))]); + + // Mark that task have been matched by overwriting their handles + start_array[i].xHandle = NULL; + end_array[j].xHandle = NULL; + break; + } + } + } + + // Print unmatched tasks + for (int i = 0; i < start_array_size; i++) { + if (start_array[i].xHandle != NULL) { + ESP_LOGI(TAG, "| %s | Deleted", start_array[i].pcTaskName); + } + } + for (int i = 0; i < end_array_size; i++) { + if (end_array[i].xHandle != NULL) { + ESP_LOGI(TAG, "| %s | Created", end_array[i].pcTaskName); + } + } + printf("\n"); + ret = ESP_OK; + +exit: // Common return path + if (start_array) { + free(start_array); + start_array = NULL; + } + if (end_array) { + free(end_array); + end_array = NULL; + } + return ret; +#else + ESP_LOGW(TAG, "Please enbale `CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID` and `CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS` in menuconfig"); + return ESP_FAIL; +#endif +} + +void test_print_cpuloading(void *arg) +{ + while (s_cpu_test_task_flag) { + audio_sys_get_real_time_stats(); + int total_ram_size_after = heap_caps_get_free_size(MALLOC_CAP_8BIT); + int internal_ram_size_after = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + int psram_size_after = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + + ESP_LOGI(TAG, "total ram consume: %d KB", (total_ram_size_before - total_ram_size_after)/1024); + ESP_LOGI(TAG, "internal ram consume: %d KB", (internal_ram_size_before - internal_ram_size_after)/1024); + ESP_LOGI(TAG, "psram consume: %d KB\n\n", (psram_size_before - psram_size_after)/1024); + } + vTaskDelete(NULL); +} + +TEST_CASE(">>>>>>>> audio_front_end SR cpu loading and memory info <<<<<<<<", "[afe]") +{ + srmodel_list_t *models = esp_srmodel_init("model"); + if (models!=NULL) { + for (int i=0; i < models->num; i++) { + printf("Load: %s\n", models->model_name[i]); + } + } + char *wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL); + printf("wn_name: %s\n", wn_name); + + total_ram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT); + internal_ram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + psram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + + esp_afe_sr_iface_t *afe_handle = (esp_afe_sr_iface_t *)&ESP_AFE_SR_HANDLE; + afe_config_t afe_config = AFE_CONFIG_DEFAULT(); + afe_config.wakenet_model_name = wn_name; + + afe_data = afe_handle->create_from_config(&afe_config); + if (!afe_data) { + printf("afe_data is null!\n"); + return; + } + + s_cpu_test_task_flag = 1; + xTaskCreatePinnedToCore(&test_feed_Task, "feed", 8 * 1024, (void *)afe_handle, 5, NULL, 0); + xTaskCreatePinnedToCore(&test_detect_Task, "detect", 8 * 1024, (void *)afe_handle, 5, NULL, 1); + xTaskCreatePinnedToCore(&test_print_cpuloading, "cpuloading", 4 * 1024, NULL, 5, NULL, 1); + + vTaskDelay(10000 / portTICK_PERIOD_MS); + s_cpu_test_task_flag = 0; + + vTaskDelay(2000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "destroy\n"); + afe_handle->destroy(afe_data); + afe_data = NULL; + esp_srmodel_deinit(models); + ESP_LOGI(TAG, "successful\n"); +} + /******************************************** Divide VC Test ********************************************/ -TEST_CASE("audio_front_end VC create/destroy API & memory leak", "[afe]") +TEST_CASE(">>>>>>>> audio_front_end VC create/destroy API & memory leak <<<<<<<<", "[afe]") { int start_total_mem_size = 0; int start_internal_mem_size = 0; @@ -183,4 +416,37 @@ TEST_CASE("audio_front_end VC create/destroy API & memory leak", "[afe]") } } } -} \ No newline at end of file +} + +TEST_CASE(">>>>>>>> audio_front_end VC cpu loading and memory info <<<<<<<<", "[afe]") +{ + total_ram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT); + internal_ram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + psram_size_before = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + + esp_afe_sr_iface_t *afe_handle = (esp_afe_sr_iface_t *)&ESP_AFE_VC_HANDLE; + afe_config_t afe_config = AFE_CONFIG_DEFAULT(); + afe_config.wakenet_init = false; + afe_config.voice_communication_init = true; + afe_config.voice_communication_agc_init = true; + + afe_data = afe_handle->create_from_config(&afe_config); + if (!afe_data) { + printf("afe_data is null!\n"); + return; + } + + s_cpu_test_task_flag = 1; + xTaskCreatePinnedToCore(&test_feed_Task, "feed", 8 * 1024, (void *)afe_handle, 5, NULL, 0); + xTaskCreatePinnedToCore(&test_detect_Task, "detect", 8 * 1024, (void *)afe_handle, 5, NULL, 1); + xTaskCreatePinnedToCore(&test_print_cpuloading, "cpuloading", 4 * 1024, NULL, 5, NULL, 1); + + vTaskDelay(20000 / portTICK_PERIOD_MS); + s_cpu_test_task_flag = 0; + + vTaskDelay(2000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "destroy\n"); + afe_handle->destroy(afe_data); + afe_data = NULL; + ESP_LOGI(TAG, "successful\n"); +} diff --git a/test_apps/esp-sr/sdkconfig.ci.wn9_hilexin b/test_apps/esp-sr/sdkconfig.ci.wn9_hilexin index ac49855..da56d50 100644 --- a/test_apps/esp-sr/sdkconfig.ci.wn9_hilexin +++ b/test_apps/esp-sr/sdkconfig.ci.wn9_hilexin @@ -401,6 +401,8 @@ CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y # # Boot ROM Behavior @@ -1171,8 +1173,10 @@ CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 -# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set -# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y # end of Kernel # @@ -1189,6 +1193,7 @@ CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y # CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y # CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set # CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set @@ -1744,6 +1749,7 @@ CONFIG_VFS_SUPPORT_DIR=y CONFIG_VFS_SUPPORT_SELECT=y CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 # # Host File System I/O (Semihosting)