/* * @Author : stark1898y 1658608470@qq.com * @Date : 2024-09-13 15:23:04 * @LastEditors : stark1898y 1658608470@qq.com * @LastEditTime : 2024-09-13 15:41:24 * @FilePath : \JT-DT-YD4N02A_RTT_MRS-4G\bsp\src\bsp_cpu_usage.c * @Description : * * Copyright (c) 2024 by yzy, All Rights Reserved. */ #include #include #include "bsp_cpu_usage.h" #define LOG_TAG "bsp_cpu_usage" // 该模块对应的标签。不定义时,默认:NO_TAG #define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别 #include // 必须在 LOG_TAG 与 LOG_LVL 下面 #if 1 #define CPU_USAGE_CALC_TICK 1000 #define CPU_USAGE_LOOP 100 static rt_uint8_t cpu_usage_major = 0, cpu_usage_minor = 0; static rt_uint32_t total_count = 0; static void _CPU_Usage_IdleHook(void) { rt_tick_t tick; rt_uint32_t count; volatile rt_uint32_t loop; if (total_count == 0) { /* get total count */ rt_enter_critical(); tick = rt_tick_get(); while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK) { total_count++; loop = 0; while (loop < CPU_USAGE_LOOP) loop++; } rt_exit_critical(); } count = 0; /* get CPU usage */ tick = rt_tick_get(); while (rt_tick_get() - tick < CPU_USAGE_CALC_TICK) { count++; loop = 0; while (loop < CPU_USAGE_LOOP) loop++; } /* calculate major and minor */ if (count < total_count) { count = total_count - count; cpu_usage_major = (count * 100) / total_count; cpu_usage_minor = ((count * 100) % total_count) * 100 / total_count; } else { total_count = count; /* no CPU usage */ cpu_usage_major = 0; cpu_usage_minor = 0; } } void CPU_Usage_Get(rt_uint8_t *major, rt_uint8_t *minor) { RT_ASSERT(major != RT_NULL); RT_ASSERT(minor != RT_NULL); *major = cpu_usage_major; *minor = cpu_usage_minor; } int CPU_Usage_Init() { LOG_I("CPU Usage Init"); /* 设置空闲线程钩子函数 */ return rt_thread_idle_sethook(_CPU_Usage_IdleHook); } #ifdef RT_USING_COMPONENTS_INIT INIT_PREV_EXPORT(CPU_Usage_Init); #endif //static rt_thread_t get_cpu_use_thread = RT_NULL; // //static void get_cpu_use_thread_entry(void *parameter) //{ // rt_uint8_t major, minor; // // while (1) // { // /* 获取CPU利用率数据 */ // CPU_Usage_Get(&major, &minor); // // /* 打印CPU利用率 */ // rt_kprintf("CPU利用率 = %d.%d%%\r\n", major, minor); // // rt_thread_delay(1000); /* 延时1000个tick */ // } //} //static void hook_of_scheduler(struct rt_thread* from, struct rt_thread* to) //{ // rt_kprintf("from: %s --> to: %s \n", from->name , to->name); //} int CPU_Usage(void) { /* 设置调度器钩子 */ // rt_scheduler_sethook(hook_of_scheduler); // CPU_Usage_Init(); // get_cpu_use_thread = /* 线程控制块指针 */ // rt_thread_create("get_cpu_use", /* 线程名字 */ // get_cpu_use_thread_entry, /* 线程入口函数 */ // RT_NULL, /* 线程入口函数参数 */ // 512, /* 线程栈大小 */ // 5, /* 线程的优先级 */ // 20); /* 线程时间片 */ // // /* 启动线程,开启调度 */ // if (get_cpu_use_thread != RT_NULL) // rt_thread_startup(get_cpu_use_thread); // else // return -1; rt_uint8_t major, minor; /* 获取CPU利用率数据 */ CPU_Usage_Get(&major, &minor); /* 打印CPU利用率 */ LOG_D("CPU利用率 = %d.%d%%", major, minor); return 0; } #ifdef FINSH_USING_MSH MSH_CMD_EXPORT(CPU_Usage, CPU_Usage); #endif #endif #if 0 #include #define HWTIMER_DEV_NAME "timer1" /* 递增 count 作为 cpu tick 使用,不可被设置,只可单调递增 */ rt_uint64_t count = 0; /* 当 CPU tick 到达 timeout_tick 时触发回调 */ rt_uint64_t timeout_tick = 0; void (*hwtimer_timeout)(void *param); void *parameter = RT_NULL; /* 精度 ns */ static float cortexm_cputime_getres(void) { return 10000; } /* cpu tick */ static uint64_t cortexm_cputime_gettime(void) { return count; } // /* 设置超时时间及函数 */ // static int cortexm_cputime_settimeout(uint64_t tick, void (*timeout)(void *param), void *param) // { // timeout_tick = tick; // hwtimer_timeout = timeout; // parameter = param; // return 0; // } /* 定义 ops */ const static struct rt_clock_cputime_ops _cpustime_ops = { cortexm_cputime_getres, cortexm_cputime_gettime // cortexm_cputime_settimeout }; /* 初始化 ops */ int cortexm_cputime_init(void) { /* bsp 在这样使用的时候,不用管内部有没有实现,这个函数会覆盖掉内部的实现 */ clock_cpu_setops(&_cpustime_ops); return 0; } INIT_BOARD_EXPORT(cortexm_cputime_init); /* 硬件定时器超时函数 */ static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size) { count++; if(count == timeout_tick) { /* 到达指定时间后清空到达时间,并触发回调 */ timeout_tick = 0; if(hwtimer_timeout != RT_NULL) hwtimer_timeout(parameter); } return 0; } /* 硬件定时器初始化 */ static int hwtimer_init() { rt_err_t ret = RT_EOK; rt_hwtimerval_t timeout_s; rt_device_t hw_dev = RT_NULL; rt_hwtimer_mode_t mode; rt_uint32_t freq = 1000000; hw_dev = rt_device_find(HWTIMER_DEV_NAME); if (hw_dev == RT_NULL) { /* 硬件定时器失败时,清空设置超时的函数,使 cputime 不可用, 防止使用 rt_cputime_sleep() 时卡死 */ // _cpustime_ops.cputime_settimeout = RT_NULL; LOG_E("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME); return RT_ERROR; } ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR); if (ret != RT_EOK) { // _cpustime_ops.cputime_settimeout = RT_NULL; LOG_E("open %s device failed!\n", HWTIMER_DEV_NAME); return ret; } /* 设置硬件定时器的超时时间 */ rt_device_set_rx_indicate(hw_dev, timeout_cb); rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq); mode = HWTIMER_MODE_PERIOD; ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode); if (ret != RT_EOK) { // _cpustime_ops.cputime_settimeout = RT_NULL; LOG_E("set mode failed! ret is :%d\n", ret); return ret; } timeout_s.sec = 0; timeout_s.usec = 10; /* 设置硬件定时器的精度,这里应和上述的 cortexm_cputime_getres 函数保持一致 */ if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s)) { // _cpustime_ops.cputime_settimeout = RT_NULL; LOG_E("set timeout value failed\n"); return RT_ERROR; } return ret; } INIT_APP_EXPORT(hwtimer_init); #endif