CPU使用百分比测量

1 CPU使用百分比测量

1.1 需求概述

在这里插入图片描述

1.2 设计原理

在这里插入图片描述

1.3 设计实现

特殊代码块:
在这里插入图片描述
统计使用百分比:
在这里插入图片描述
相关代码如下:

// 空闲任务计数与最大计数
uint32_t idleCount;
uint32_t idleMaxCount;

static void initCpuUsageStat (void);
static void checkCpuUsage (void);
static void cpuUsageSyncWithSysTick (void);

static float cpuUsage;                      // cpu使用率统计
static uint32_t enableCpuUsageStat;         // 是否使能cpu统计

/**********************************************************************************************************
** Function name        :   initCpuUsageStat
** Descriptions         :   初始化cpu统计
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
static void initCpuUsageStat (void)
{
    idleCount = 0;
    idleMaxCount = 0;
    cpuUsage = 0;
    enableCpuUsageStat = 0;
}

/**********************************************************************************************************
** Function name        :   checkCpuUsage
** Descriptions         :   检查cpu使用率
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
static void checkCpuUsage (void)
{
    // 与空闲任务的cpu统计同步
    if (enableCpuUsageStat == 0)
    {
        enableCpuUsageStat = 1;
        tickCount = 0;
        return;
    }

    if (tickCount == TICKS_PER_SEC)
    {
        // 统计最初1s内的最大计数值
        idleMaxCount = idleCount;
        idleCount = 0;

        // 计数完毕,开启调度器,允许切换到其它任务
        tTaskSchedEnable();
    }
    else if (tickCount % TICKS_PER_SEC == 0)
    {
        // 之后每隔1s统计一次,同时计算cpu利用率
        cpuUsage = 100 - (idleCount * 100.0 / idleMaxCount);
        idleCount = 0;
    }
}
/**********************************************************************************************************
** Function name        :   tTaskSystemTickHandler
** Descriptions         :   系统时钟节拍处理。
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
void tTaskSystemTickHandler (void) 
{
    tNode * node;
    
    // 进入临界区,以保护在整个任务调度与切换期间,不会因为发生中断导致currentTask和nextTask可能更改
    uint32_t status = tTaskEnterCritical();
    
    // 检查所有任务的delayTicks数,如果不0的话,减1。
    for (node = tTaskDelayedList.headNode.nextNode; node != &(tTaskDelayedList.headNode); node = node->nextNode)
    {
        tTask * task = tNodeParent(node, tTask, delayNode);
        if (--task->delayTicks == 0) 
        {
            // 如果任务还处于等待事件的状态,则将其从事件等待队列中唤醒
            if (task->waitEvent) 
            {
                // 此时,消息为空,等待结果为超时
                tEventRemoveTask(task, (void *)0, tErrorTimeout);
            }

            // 将任务从延时队列中移除
            tTimeTaskWakeUp(task);

            // 将任务恢复到就绪状态
            tTaskSchedRdy(task);            
        }
    }

    // 检查下当前任务的时间片是否已经到了
    if (--currentTask->slice == 0) 
    {
        // 如果当前任务中还有其它任务的话,那么切换到下一个任务
        // 方法是将当前任务从队列的头部移除,插入到尾部
        // 这样后面执行tTaskSched()时就会从头部取出新的任务取出新的任务作为当前任务运行
        if (tListCount(&taskTable[currentTask->prio]) > 0) 
        {            
            tListRemoveFirst(&taskTable[currentTask->prio]);
            tListAddLast(&taskTable[currentTask->prio], &(currentTask->linkNode));
       
            // 重置计数器
            currentTask->slice = TINYOS_SLICE_MAX;
        }
    }

    // 节拍计数增加
    tickCount++;

    // 检查cpu使用率
    checkCpuUsage();

    // 退出临界区
    tTaskExitCritical(status); 

    // 通知定时器模块节拍事件
    tTimerModuleTickNotify();

    // 这个过程中可能有任务延时完毕(delayTicks = 0),进行一次调度。
    tTaskSched();
}

/**********************************************************************************************************
** Function name        :   cpuUsageSyncWithSysTick
** Descriptions         :   为检查cpu使用率与系统时钟节拍同步
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
static void cpuUsageSyncWithSysTick (void)
{
    // 等待与时钟节拍同步
    while (enableCpuUsageStat == 0)
    {
        ;;
    }
}

/**********************************************************************************************************
** Function name        :   cpuUsageSyncWithSysTick
** Descriptions         :   为检查cpu使用率与系统时钟节拍同步
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
float tCpuUsageGet (void)
{
    float usage = 0;

    uint32_t status = tTaskEnterCritical();
    usage = cpuUsage;
    tTaskExitCritical(status);

    return usage;
}

// 用于空闲任务的任务结构和堆栈空间
tTask tTaskIdle;
tTaskStack idleTaskEnv[TINYOS_IDLETASK_STACK_SIZE];

void idleTaskEntry (void * param) {
    // 禁止调度,防止后面在创建任务时切换到其它任务中去
    tTaskSchedDisable();

    // 初始化App相关配置
    tInitApp();

    // 初始化定时器任务
    tTimerInitTask();

    // 启动系统时钟节拍
    tSetSysTickPeriod(TINYOS_SYSTICK_MS);

    // 等待与时钟同步
    cpuUsageSyncWithSysTick();

    for (;;)
    {
        uint32_t status = tTaskEnterCritical();
        idleCount++;
        tTaskExitCritical(status);
    }
}

int main () 
{
    // 优先初始化tinyOS的核心功能
    tTaskSchedInit();

    // 初始化延时队列
    tTaskDelayedInit();

    // 初始化定时器模块
    tTimerModuleInit();

    // 初始化时钟节拍
    tTimeTickInit();

    // 初始化cpu统计
    initCpuUsageStat();

    // 创建空闲任务
    tTaskInit(&tTaskIdle, idleTaskEntry, (void *)0, TINYOS_PRO_COUNT - 1, idleTaskEnv, TINYOS_IDLETASK_STACK_SIZE);
    
    // 这里,不再指定先运行哪个任务,而是自动查找最高优先级的任务运行
    nextTask = tTaskHighestReady();

    // 切换到nextTask, 这个函数永远不会返回
    tTaskRunFirst();
    return 0;
}



参考资料:

  1. 【李述铜】从0到1自己动手写嵌入式操作系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值