273 lines
8.2 KiB
C
273 lines
8.2 KiB
C
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright 2015-2022 Espressif Systems (Shanghai) PTE LTD
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "stats.h"
|
|
#include <unistd.h>
|
|
#include "esp_log.h"
|
|
#include "esp_hosted_transport_init.h"
|
|
|
|
#if TEST_RAW_TP || ESP_PKT_STATS
|
|
static const char TAG[] = "stats";
|
|
#endif
|
|
|
|
#if ESP_PKT_STATS || TEST_RAW_TP
|
|
#define ESP_PKT_STATS_REPORT_INTERVAL 10
|
|
struct pkt_stats_t pkt_stats;
|
|
#endif
|
|
|
|
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
|
|
/* These functions are only for debugging purpose
|
|
* Please do not enable in production environments
|
|
*/
|
|
static esp_err_t log_real_time_stats(TickType_t xTicksToWait) {
|
|
TaskStatus_t *start_array = NULL, *end_array = NULL;
|
|
UBaseType_t start_array_size, end_array_size;
|
|
uint32_t start_run_time, end_run_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);
|
|
if (start_array == NULL) {
|
|
ret = ESP_ERR_NO_MEM;
|
|
goto exit;
|
|
}
|
|
/*Get current task states*/
|
|
start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time);
|
|
if (start_array_size == 0) {
|
|
ret = ESP_ERR_INVALID_SIZE;
|
|
goto exit;
|
|
}
|
|
|
|
vTaskDelay(xTicksToWait);
|
|
|
|
/*Allocate array to store tasks states post delay*/
|
|
end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
|
|
end_array = malloc(sizeof(TaskStatus_t) * end_array_size);
|
|
if (end_array == NULL) {
|
|
ret = ESP_ERR_NO_MEM;
|
|
goto exit;
|
|
}
|
|
/*Get post delay task states*/
|
|
end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time);
|
|
if (end_array_size == 0) {
|
|
ret = ESP_ERR_INVALID_SIZE;
|
|
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) {
|
|
ret = ESP_ERR_INVALID_STATE;
|
|
goto exit;
|
|
}
|
|
|
|
ESP_LOGI(TAG,"| Task | Run Time | Percentage\n");
|
|
/*Match each task in start_array to those in the end_array*/
|
|
for (int i = 0; i < start_array_size; i++) {
|
|
int k = -1;
|
|
for (int j = 0; j < end_array_size; j++) {
|
|
if (start_array[i].xHandle == end_array[j].xHandle) {
|
|
k = j;
|
|
/*Mark that task have been matched by overwriting their handles*/
|
|
start_array[i].xHandle = NULL;
|
|
end_array[j].xHandle = NULL;
|
|
break;
|
|
}
|
|
}
|
|
/*Check if matching task found*/
|
|
if (k >= 0) {
|
|
uint32_t task_elapsed_time = end_array[k].ulRunTimeCounter - start_array[i].ulRunTimeCounter;
|
|
uint32_t percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * portNUM_PROCESSORS);
|
|
ESP_LOGI(TAG,"| %s | %d | %d%%\n", start_array[i].pcTaskName, task_elapsed_time, percentage_time);
|
|
}
|
|
}
|
|
|
|
/*Print unmatched tasks*/
|
|
for (int i = 0; i < start_array_size; i++) {
|
|
if (start_array[i].xHandle != NULL) {
|
|
ESP_LOGI(TAG,"| %s | Deleted\n", start_array[i].pcTaskName);
|
|
}
|
|
}
|
|
for (int i = 0; i < end_array_size; i++) {
|
|
if (end_array[i].xHandle != NULL) {
|
|
ESP_LOGI(TAG,"| %s | Created\n", end_array[i].pcTaskName);
|
|
}
|
|
}
|
|
ret = ESP_OK;
|
|
|
|
exit: /*Common return path*/
|
|
if (start_array)
|
|
free(start_array);
|
|
if (end_array)
|
|
free(end_array);
|
|
return ret;
|
|
}
|
|
|
|
static void log_runtime_stats_task(void* pvParameters) {
|
|
while (1) {
|
|
ESP_LOGI(TAG,"\n\nGetting real time stats over %d ticks\n", STATS_TICKS);
|
|
if (log_real_time_stats(STATS_TICKS) == ESP_OK) {
|
|
ESP_LOGI(TAG,"Real time stats obtained\n");
|
|
} else {
|
|
ESP_LOGE(TAG,"Error getting real time stats\n");
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(1000*2));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if TEST_RAW_TP
|
|
uint64_t test_raw_tp_rx_len;
|
|
uint64_t test_raw_tp_tx_len;
|
|
|
|
void debug_update_raw_tp_rx_count(uint16_t len)
|
|
{
|
|
test_raw_tp_rx_len += (len);
|
|
}
|
|
|
|
// static buffer to hold tx data during test
|
|
DMA_ATTR static uint8_t tx_buf[TEST_RAW_TP__BUF_SIZE];
|
|
|
|
extern volatile uint8_t datapath;
|
|
static void raw_tp_tx_task(void* pvParameters)
|
|
{
|
|
int ret;
|
|
interface_buffer_handle_t buf_handle = {0};
|
|
uint8_t *raw_tp_tx_buf = NULL;
|
|
uint32_t *ptr = NULL;
|
|
uint16_t i = 0;
|
|
|
|
sleep(5);
|
|
|
|
// initialise the static buffer
|
|
raw_tp_tx_buf = tx_buf;
|
|
ptr = (uint32_t*)raw_tp_tx_buf;
|
|
// initialise the tx buffer
|
|
for (i=0; i<(TEST_RAW_TP__BUF_SIZE/4-1); i++, ptr++)
|
|
*ptr = 0xdeadbeef;
|
|
|
|
for (;;) {
|
|
|
|
if (!datapath) {
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
|
|
buf_handle.if_type = ESP_TEST_IF;
|
|
buf_handle.if_num = 0;
|
|
|
|
buf_handle.payload = raw_tp_tx_buf;
|
|
buf_handle.payload_len = TEST_RAW_TP__BUF_SIZE;
|
|
// free the buffer after it has been sent
|
|
buf_handle.free_buf_handle = NULL;
|
|
buf_handle.priv_buffer_handle = buf_handle.payload;
|
|
|
|
ret = send_to_host_queue(&buf_handle, PRIO_Q_OTHERS);
|
|
|
|
if (ret) {
|
|
ESP_LOGE(TAG,"Failed to send to queue\n");
|
|
continue;
|
|
}
|
|
test_raw_tp_tx_len += (TEST_RAW_TP__BUF_SIZE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if TEST_RAW_TP || ESP_PKT_STATS
|
|
|
|
static void stats_timer_func(void* arg)
|
|
{
|
|
#if TEST_RAW_TP
|
|
static int32_t cur = 0;
|
|
double actual_bandwidth_rx = 0;
|
|
double actual_bandwidth_tx = 0;
|
|
int32_t div = 1024;
|
|
|
|
actual_bandwidth_tx = (test_raw_tp_tx_len*8)/TEST_RAW_TP__TIMEOUT;
|
|
actual_bandwidth_rx = (test_raw_tp_rx_len*8)/TEST_RAW_TP__TIMEOUT;
|
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
|
ESP_LOGI(TAG,"%lu-%lu sec Rx: %.2f Tx: %.2f kbps", cur, cur + TEST_RAW_TP__TIMEOUT, actual_bandwidth_rx/div, actual_bandwidth_tx/div);
|
|
#else
|
|
ESP_LOGI(TAG,"%u-%u sec Rx: %.2f Tx: %.2f kbps", cur, cur + TEST_RAW_TP__TIMEOUT, actual_bandwidth_rx/div, actual_bandwidth_tx/div);
|
|
#endif
|
|
cur += TEST_RAW_TP__TIMEOUT;
|
|
test_raw_tp_rx_len = test_raw_tp_tx_len = 0;
|
|
#endif
|
|
#if ESP_PKT_STATS
|
|
ESP_LOGI(TAG, "slave StaRxQLoad: %8lu \nH=>S: sta: in: %8lu out: %8lu fail: %8lu \nH<=S: sta: in: %8lu out: %8lu \n serial : in: %8lu rsp: %8lu evt: %8lu",
|
|
pkt_stats.slave_wifi_rx_msg_loaded,
|
|
pkt_stats.hs_bus_sta_in,pkt_stats.hs_bus_sta_out, pkt_stats.hs_bus_sta_fail,
|
|
pkt_stats.sta_sh_in,pkt_stats.sta_sh_out,
|
|
pkt_stats.serial_rx, pkt_stats.serial_tx_total, pkt_stats.serial_tx_evt);
|
|
|
|
#endif
|
|
}
|
|
|
|
static void start_timer_to_display_stats(int periodic_time_sec)
|
|
{
|
|
test_args_t args = {0};
|
|
esp_timer_handle_t raw_tp_timer = {0};
|
|
esp_timer_create_args_t create_args = {
|
|
.callback = &stats_timer_func,
|
|
.arg = &args,
|
|
.name = "raw_tp_timer",
|
|
};
|
|
|
|
ESP_ERROR_CHECK(esp_timer_create(&create_args, &raw_tp_timer));
|
|
|
|
args.timer = raw_tp_timer;
|
|
|
|
ESP_ERROR_CHECK(esp_timer_start_periodic(raw_tp_timer, SEC_TO_USEC(periodic_time_sec)));
|
|
}
|
|
#endif
|
|
|
|
|
|
#if TEST_RAW_TP
|
|
void process_test_capabilities(uint8_t capabilities)
|
|
{
|
|
ESP_LOGD(TAG, "capabilites: %d", capabilities);
|
|
if ((capabilities & ESP_TEST_RAW_TP__ESP_TO_HOST) ||
|
|
(capabilities & ESP_TEST_RAW_TP__BIDIRECTIONAL)) {
|
|
assert(xTaskCreate(raw_tp_tx_task , "raw_tp_tx_task",
|
|
CONFIG_ESP_DEFAULT_TASK_STACK_SIZE, NULL ,
|
|
CONFIG_ESP_DEFAULT_TASK_PRIO, NULL) == pdTRUE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void create_debugging_tasks(void)
|
|
{
|
|
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
|
|
assert(xTaskCreate(log_runtime_stats_task, "log_runtime_stats_task",
|
|
CONFIG_ESP_DEFAULT_TASK_STACK_SIZE, NULL,
|
|
CONFIG_ESP_DEFAULT_TASK_PRIO, NULL) == pdTRUE);
|
|
#endif
|
|
|
|
#if TEST_RAW_TP || ESP_PKT_STATS
|
|
start_timer_to_display_stats(ESP_PKT_STATS_REPORT_INTERVAL);
|
|
#endif
|
|
}
|
|
|
|
uint8_t debug_get_raw_tp_conf(void) {
|
|
uint8_t raw_tp_cap = 0;
|
|
#if TEST_RAW_TP
|
|
raw_tp_cap |= ESP_TEST_RAW_TP;
|
|
ESP_LOGI(TAG, "\n\n***** Slave: Raw Throughput testing (Report per %u sec)*****\n", CONFIG_ESP_RAW_TP_REPORT_INTERVAL);
|
|
#endif
|
|
return raw_tp_cap;
|
|
}
|