单片机CPU负载率测试

CUT(cpu utilization test)负载率测试

传送门

1. 前言

目前在开发过程中,需要检测任务的CPU占用率,而很多的系统中是不支持像FreeRTOS、RT-Thread等操作系统可以支持CPU占用率的统计,因此实现了CUT去实现该需求。

2. CUT概述

2.1 功能介绍

  • 在一定时间内任务的运行时间统计
  • 在一定时间内任务的运行次数统计
  • 在一定时间内任务的负载率计算
  • 在一定时间内任务的平均运行时间计算
  • 统计数据打印
  • 命令行方式控制测试开始/结束

需要资源:

  1. 定时器:提供时间
  2. CUT组件:运行时间计算
  3. SEGGERT RTT:日志打印
  4. Letter Shell:命令行交互

2.2 适用场景

适用于前后台的系统(任务 + 中断)。

适用于优先级高的任务发生后完全执行完毕,没有类似信号量、互斥锁等导致任务运行一半中途跳转的情况(如第三部分流程图所示)。

3. 工作原理

  • 时间统计

    由于我们的任务运行时间基本都是us、ms级别,在一般的系统中,系统时间都是以ms为单位计算的,因此不足以满足我们的任务运行时间。因此使用定时器的Counter来用作时间点计算(例如4MHz的时钟频率,那么一个Tick值就是0.25us)。

  • 单次任务运行时间计算(非嵌套)

    在进入任务的时候记录Counter(A),任务结束的时候记录Counter(B),通过B和A计算出运行时间。

    注意:定时器的定时周期要大于任务的执行时间,比如定时周期10ms,我的任务执行时间要小于10ms。如果定时为5ms,执行11ms,那么只能计算出任务时间为6ms,中间会丢失5ms,因此这里需要估算一个大概的范围,例如我定时器时钟频率4MHz,那么我计数周期就设定4000000,定时周期1s,足以覆盖任务执行时间。

  • 单次任务运行时间计算(嵌套)

    如下图所示,任务A会被任务B打断。当任务A开始,在任务A的数据缓存中记录Counter,此时将任务A压栈(为了任务B结束后,能知道是回到A任务),任务B开始,获取当前Counter值,先将当前A任务运行时间结算累加,然后在任务B的数据缓存中记录Counter并将任务B压栈,任务B执行完毕,获取当前Counter值,计算出任务B的运行时间累加,任务B出栈,然后获取当前Counter值更新到任务A中,任务A继续执行,任务A执行完毕,结算剩下运行时间累加,任务A出栈。

在这里插入图片描述

  • 时间补偿

    时间补偿就是在计算的时候除去测试代码消耗掉的时间,该部分时间通过测试验证得出一个大致的范围:

    任务空跑测试时间负载率
    总运行时间10s
    10ms任务1079.750us0.01%
    500ms任务22.250us0.00%
    10000ms任务11.000us0.00%

    空跑(非嵌套)测试下来执行一次测试代码 ≈ 1us

    任务空跑嵌套测试时间负载率
    总运行时间10s
    10ms任务2579.000us0.025%
    500ms任务2602.250us0.026%
    10000ms任务1071.000us0.010%

    空跑(非嵌套)测试下来执行一次测试代码 ≈ 2.5us

    因此时间补偿有两个点,一个是任务被打断的时候做一次时间补偿1.5us(2.5 - 1),一次是任务结束的时候做一次时间补偿1us

4. 测试数据

下面一个是通过手动测试,IO口输出高低电平,通过示波器采集数据的方式统计的数据,一个是使用CUT组件进行测试统计的数据:

手动测试数据时间负载率次数平均值
运行时间13.98s
2ms7.2%7000
5ms4.73%2800
10ms34.36%1399
LPIT_ISR11.61%
FTM_ISR0.26%
代码测试数据时间负载率次数平均值
运行时间27775000us
2ms1659762.920us6.491%14000118.554us
5ms1292408.448us5.054%5601230.746us
10ms8987586.647us35.150%28013208.746us
LPIT_ISR3054445.647us11.945%27775010.997us
FTM_ISR71475.496us0.279%699810.213us

5. 使用方式

如下面代码所示,在任务的开始和结束增加CUT_TASK_ENTRY/CUT_TASK_LEAVE,传入定义好的任务名称:

void Task_10ms(void)
{
	extern void shellTask(void *param);

	shellTask(&shell);

	CUT_TASK_ENTRY(TASK_10ms);

	// code...

	CUT_TASK_LEAVE(TASK_10ms);
}

如下图所示,通过命令行的方式控制测试的开始/关闭,关闭后会输出测试结果:

打印方式:SEGGERT RTT
命令行交互: Letter Shell
将上述两个组件配合CUT使用实现下图效果:

在这里插入图片描述

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值