|
@@ -0,0 +1,202 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2006-2025, RT-Thread Development Team
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: Apache-2.0
|
|
|
+ *
|
|
|
+ * Change Logs:
|
|
|
+ * Date Author Notes
|
|
|
+ * 2025-07-03 rcitach test case for irq latency
|
|
|
+ */
|
|
|
+
|
|
|
+#include <rtthread.h>
|
|
|
+#include <rtdevice.h>
|
|
|
+#include <rtservice.h>
|
|
|
+#include <utest.h>
|
|
|
+#include <utest_assert.h>
|
|
|
+#include <perf_tc.h>
|
|
|
+
|
|
|
+#define RET_INT 0
|
|
|
+#define RET_DECIMALS 1
|
|
|
+
|
|
|
+#define GET_INT(num) split_double(num, RET_INT)
|
|
|
+#define GET_DECIMALS(num) split_double(num, RET_DECIMALS)
|
|
|
+
|
|
|
+static rt_device_t hw_dev = RT_NULL;
|
|
|
+static rt_hwtimerval_t timeout_s = {0};
|
|
|
+
|
|
|
+typedef rt_err_t (*testcase_function)(rt_perf_t *perf);
|
|
|
+testcase_function test_func_ptrs[] =
|
|
|
+{
|
|
|
+ context_switch_test,
|
|
|
+ rt_perf_thread_sem,
|
|
|
+ rt_perf_thread_event,
|
|
|
+ rt_perf_thread_mq,
|
|
|
+ rt_perf_thread_mbox,
|
|
|
+ rt_perf_irq_latency, /* Timer Interrupt Source */
|
|
|
+ RT_NULL
|
|
|
+};
|
|
|
+
|
|
|
+static rt_uint32_t rt_perf_get_timer_us(void)
|
|
|
+{
|
|
|
+ rt_hwtimerval_t timer_val = {0};
|
|
|
+ if (hw_dev && rt_device_read(hw_dev, 0, &timer_val, sizeof(rt_hwtimerval_t)))
|
|
|
+ {
|
|
|
+ return (rt_uint32_t)(timer_val.sec * 1000000u + timer_val.usec); /* return us */
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void rt_perf_start_impl(rt_perf_t *perf, rt_hwtimerval_t *timeout)
|
|
|
+{
|
|
|
+ if (hw_dev)
|
|
|
+ {
|
|
|
+ if (timeout == RT_NULL)
|
|
|
+ timeout = &timeout_s;
|
|
|
+ rt_device_write(hw_dev, 0, timeout, sizeof(rt_hwtimerval_t));
|
|
|
+ }
|
|
|
+ perf->begin_time = rt_perf_get_timer_us();
|
|
|
+}
|
|
|
+
|
|
|
+void rt_perf_stop(rt_perf_t *perf)
|
|
|
+{
|
|
|
+ perf->real_time = rt_perf_get_timer_us() - perf->begin_time;
|
|
|
+
|
|
|
+ if(perf->local_modify) perf->local_modify(perf);
|
|
|
+ if (perf->real_time > perf->max_time)
|
|
|
+ {
|
|
|
+ perf->max_time = perf->real_time;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (perf->real_time < perf->min_time)
|
|
|
+ {
|
|
|
+ perf->min_time = perf->real_time;
|
|
|
+ }
|
|
|
+
|
|
|
+ perf->count++;
|
|
|
+ perf->tot_time += perf->real_time;
|
|
|
+
|
|
|
+ if(hw_dev)
|
|
|
+ rt_device_control(hw_dev, HWTIMER_CTRL_STOP, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static rt_int32_t split_double(double num, rt_uint32_t type)
|
|
|
+{
|
|
|
+ if (type == RET_INT)
|
|
|
+ {
|
|
|
+ return (rt_int32_t)num;
|
|
|
+ }
|
|
|
+ else if (type == RET_DECIMALS)
|
|
|
+ {
|
|
|
+ return (rt_int32_t)((num - (rt_int32_t)num) * 10000);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return (-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (-1);
|
|
|
+}
|
|
|
+
|
|
|
+void rt_perf_dump( rt_perf_t *perf)
|
|
|
+{
|
|
|
+ static rt_uint32_t test_index = 1;
|
|
|
+ char avg_str[10] = {0};
|
|
|
+ if(perf->dump_head)
|
|
|
+ {
|
|
|
+ rt_kprintf("Test No | Test Name | Count | Total Time (us) | Max Time (us) | Min Time (us) | Avg Time (us)\n");
|
|
|
+ rt_kprintf("--------|----------------------|-------|-----------------|---------------|---------------|--------------\n");
|
|
|
+ perf->dump_head = RT_FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (perf->count)
|
|
|
+ perf->avg_time = (double)perf->tot_time / perf->count;
|
|
|
+ else
|
|
|
+ perf->avg_time = 0.0;
|
|
|
+
|
|
|
+ rt_sprintf(avg_str, "%u.%04u", GET_INT(perf->avg_time), GET_DECIMALS(perf->avg_time));
|
|
|
+
|
|
|
+ rt_kprintf("%7u | %-20s | %5u | %15u | %13u | %13u | %12s\n",
|
|
|
+ test_index++,
|
|
|
+ perf->name,
|
|
|
+ perf->count,
|
|
|
+ perf->tot_time,
|
|
|
+ perf->max_time,
|
|
|
+ perf->min_time,
|
|
|
+ avg_str);
|
|
|
+}
|
|
|
+
|
|
|
+static void rt_perf_clear(rt_perf_t *perf)
|
|
|
+{
|
|
|
+ perf->local_modify = NULL;
|
|
|
+ perf->begin_time = 0;
|
|
|
+ perf->real_time = 0;
|
|
|
+ perf->tot_time = 0;
|
|
|
+ perf->max_time = 0;
|
|
|
+ perf->min_time = RT_UINT32_MAX;
|
|
|
+ perf->count = 0;
|
|
|
+ perf->avg_time = 0;
|
|
|
+ perf->tmp_time = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void rt_perf_all_test(void)
|
|
|
+{
|
|
|
+
|
|
|
+ rt_perf_t *perf_data = rt_malloc(sizeof(rt_perf_t));
|
|
|
+ if (perf_data == RT_NULL)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ perf_data->lock = rt_mutex_create("perf", RT_IPC_FLAG_PRIO);
|
|
|
+ perf_data->dump_head = RT_TRUE;
|
|
|
+ rt_kprintf("\n === Performance Test Results Start ===\n");
|
|
|
+ for (int i = 0; test_func_ptrs[i] != RT_NULL; i++)
|
|
|
+ {
|
|
|
+ rt_perf_clear(perf_data);
|
|
|
+ if (test_func_ptrs[i](perf_data) != RT_EOK)
|
|
|
+ {
|
|
|
+ LOG_E("%s test fail",perf_data->name);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rt_kprintf("\n === Performance Test Results End ===\n");
|
|
|
+ rt_mutex_delete(perf_data->lock);
|
|
|
+ rt_free(perf_data);
|
|
|
+}
|
|
|
+
|
|
|
+static rt_err_t utest_tc_init(void)
|
|
|
+{
|
|
|
+ int ret = RT_EOK;
|
|
|
+
|
|
|
+ hw_dev = rt_device_find(UTEST_HWTIMER_DEV_NAME);
|
|
|
+ if (hw_dev == RT_NULL)
|
|
|
+ {
|
|
|
+ ret = RT_ERROR;
|
|
|
+ LOG_E("hwtimer sample run failed! can't find %s device!", UTEST_HWTIMER_DEV_NAME);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
|
|
|
+ if (ret != RT_EOK)
|
|
|
+ {
|
|
|
+ LOG_E("open %s device failed!", UTEST_HWTIMER_DEV_NAME);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ timeout_s.sec = 10; /* No modification is necessary here, use the fixed value */
|
|
|
+ timeout_s.usec = 0;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static rt_err_t utest_tc_cleanup(void)
|
|
|
+{
|
|
|
+ if(hw_dev) rt_device_close(hw_dev);
|
|
|
+ return RT_EOK;
|
|
|
+}
|
|
|
+
|
|
|
+static void testcase(void)
|
|
|
+{
|
|
|
+ UTEST_UNIT_RUN(rt_perf_all_test);
|
|
|
+}
|
|
|
+
|
|
|
+UTEST_TC_EXPORT(testcase, "testcase.pref.all", utest_tc_init, utest_tc_cleanup, 10);
|
|
|
+
|