RTX5中没有对各线程的CPU占用统计,这里使用EventRecorder统计各线程的CPU占用。
RTX_Config.h中将宏定义OS_EVR_THREAD设置为1,在rtx_evr.c中的EvrRtxThreadCreated()EvrRtxThreadSwitched()定义如下:

__WEAK void EvrRtxThreadCreated (osThreadId_t thread_id, uint32_t thread_addr, const char *name) {
#if defined(RTE_Compiler_EventRecorder)
if (name != NULL) {
(void)EventRecord2(EvtRtxThreadCreated_Name, (uint32_t)thread_id, (uint32_t)name);
} else {
(void)EventRecord2(EvtRtxThreadCreated_Addr, (uint32_t)thread_id, thread_addr);
}
#else
(void)thread_id;
(void)thread_addr;
(void)name;
#endif
}
__WEAK void EvrRtxThreadSwitched (osThreadId_t thread_id) {
#if defined(RTE_Compiler_EventRecorder)
  (void)EventRecord2(EvtRtxThreadSwitched, (uint32_t)thread_id, 0U);
#else
  (void)thread_id;
#endif
}

当线程创建后,进入EvrRtxThreadCreated()函数,通过EventRecord2()将创建的线程信息通过调试接口发送给PC,发生线程切换时,进入EvrRtxThreadSwitched(),通过EventRecord2()将切换的线程id通过调试接口发送给调试的上位机。这两个函数都是弱定义,重定义这两个函数,并统计时间周期内各线程运行的时间即可计算线程的CPU占用率。

具体实现方法如下:EvrRtxThreadCreated在线程创建时被调用,函数中统计线程的ID,并将ID存入数组中。

void EvrRtxThreadCreated (osThreadId_t thread_id, uint32_t thread_addr, const char *name)
{
    uint16_t ptr;
    osRtxThread_t *p_tcb;
    uint32_t * sp;
    for(ptr=0;ptr<MAX_THREAD_NUM;ptr++)
    {
        /* 检测到列表尾 */
        if(cpuUsage.id[ptr] == 0)
            break;

        /* 当前列表已有该线程 */
        if(cpuUsage.id[ptr] == (uint32_t)thread_id)
            return;
    }

    cpuUsage.id[ptr] = (uint32_t)thread_id;

    p_tcb = thread_id;
    sp=(uint32_t *)(p_tcb->sp);    
}

EvrRtxThreadSwitched在发生线程切换时调用,统计上一个线程的运行时间并更新当前运行线程的ID。

void EvrRtxThreadSwitched (osThreadId_t thread_id)
{
    uint16_t ptr;
    uint32_t threadRunTime;
    uint64_t time;

    /* 获取当前的运行时间(us) */
    time = GetRunTimeUs();

    /* 计算上一个线程的运行时间并更新当前线程的开始时间 */
    threadRunTime = time - cpuUsage.threadStartUs;
    cpuUsage.threadStartUs = time;

    /* 将上一个线程的运行时间累加 */
    for(ptr = 0;ptr<MAX_THREAD_NUM;ptr++)
    {
        if(cpuUsage.id[ptr]==cpuUsage.runId)
        {
            cpuUsage.time[ptr] += threadRunTime; 
        }
        if(cpuUsage.id[ptr]==0)
            break;
    }

    /* 更新当前运行线程ID */
    cpuUsage.runId = (uint32_t)thread_id;
}

CPU统计的程序每200ms执行一次,首先获取一个周期的运行时间,储存这一个周期内各个线程的运行时间,并更新下一周期的开始时间,获取当前运行的线程ID。各线程的运行时间储存在cpuUsage.usage中,除以cpuUsage.cycleTime即为各线程的占用率。

/* 各线程CPU占用率统计 */
/* 获取一个周期的时间 */
cpuUsage.cycleTime = bsp_Timer.RunTimeUs_Check(cpuUsage.startUs);

/* 储存线程运行时间 */
for(threadPtr = 0; threadPtr<MAX_THREAD_NUM; threadPtr++)
{
if(cpuUsage.id[threadPtr]==0)
break;
cpuUsage.usage[threadPtr] = cpuUsage.time[threadPtr];
}

/* 获取一个统计周期开始的时间 */
cpuUsage.startUs = bsp_Timer.RunTimeUs_Get();

/* 清除各线程的运行时间 */
for(threadPtr = 0; threadPtr<MAX_THREAD_NUM; threadPtr++)
{
if(cpuUsage.id[threadPtr]==0)
break;
cpuUsage.time[threadPtr] = 0;
}

/* 获取当前运行的线程ID */
cpuUsage.runId = (uint32_t)osThreadGetId();

/* 当前线程的开始时间即为本次统计周期的开始时间 */
cpuUsage.threadStartUs = cpuUsage.startUs;
最后修改:2023 年 09 月 18 日