277 lines
7.1 KiB
C
277 lines
7.1 KiB
C
/*
|
||
* @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 <rthw.h>
|
||
#include <rtthread.h>
|
||
|
||
#include "bsp_cpu_usage.h"
|
||
|
||
#define LOG_TAG "bsp_cpu_usage" // 该模块对应的标签。不定义时,默认:NO_TAG
|
||
#define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别
|
||
#include <ulog.h> // 必须在 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 <rtdevice.h>
|
||
|
||
#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
|
||
|
||
|
||
|
||
|
||
|
||
|