3、CPU压力测试:满负荷运算测试、多任务并发测试、中断风暴测试
CPU压力测试,说白了就是要把处理器往死里整。你得看看它在极限状态下会不会崩,会不会偷偷降频,会不会莫名其妙死机。我做了这么多年嵌入式,见过太多“平时跑得好好的,一上量就翻车”的案例了。今天咱们就把CPU压力测试的三个核心维度掰开揉碎讲清楚。
3.1 满负荷运算测试
满负荷运算测试,就是让CPU核心以100%的占用率持续运行。目的是什么?验证散热设计是否到位,电源供电是否扛得住,以及芯片本身有没有体质缺陷。
我个人习惯用两种方式来做:
- 纯整数运算:比如循环做加法、乘法,或者跑一些经典的算法如FFT、矩阵乘法。
- 浮点运算:这个更狠,因为浮点单元(FPU)功耗大、发热猛,很多芯片的短板就在这里暴露。
下面是一个简单的满负荷测试代码片段,适用于ARM Cortex-M系列:
// 满负荷整数运算测试
void cpu_stress_test(void) {
volatile uint32_t a = 0x12345678;
volatile uint32_t b = 0x87654321;
volatile uint32_t result = 0;
while(1) {
// 大量乘加运算,让ALU满负荷
for(int i = 0; i < 10000; i++) {
result = a * b + result;
result = result ^ a;
result = result << 3;
}
// 加个看门狗喂食,防止测试过程中复位
watchdog_feed();
}
}
⚠️ 注意:满负荷测试时,一定要监控芯片温度。我曾经在一个项目中,没加散热片就跑这个测试,结果芯片温度飙到110°C,直接触发热关断。嗯,那次差点把板子烧了。
测试时长建议:至少跑30分钟。如果条件允许,跑2小时以上更稳妥。为什么?因为热积累需要时间,有些芯片前10分钟没事,20分钟后就开始降频了。
3.2 多任务并发测试
满负荷测试测的是单核极限,但现实中的嵌入式系统往往是多任务的。你想想看,一个设备既要采集传感器数据,又要处理网络通信,还得刷新UI界面。这时候,多任务并发能力就成了关键。
多任务并发测试的核心思路:
- 创建多个高优先级任务,让它们同时抢占CPU资源。
- 任务之间要有数据交互,比如通过队列、信号量、共享内存。
- 观察系统是否出现死锁、优先级反转、任务饿死等问题。
我常用的测试框架是这样的:
// 多任务并发测试 - 基于FreeRTOS
void task_high_priority(void *pvParameters) {
while(1) {
// 高优先级任务:密集计算
for(int i = 0; i < 5000; i++) {
compute_heavy_math();
}
vTaskDelay(pdMS_TO_TICKS(10)); // 主动让出CPU
}
}
void task_medium_priority(void *pvParameters) {
while(1) {
// 中优先级任务:模拟外设通信
simulate_uart_transfer();
vTaskDelay(pdMS_TO_TICKS(5));
}
}
void task_low_priority(void *pvParameters) {
while(1) {
// 低优先级任务:后台日志记录
log_system_status();
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// 创建任务时,故意让优先级设置不合理,测试调度器是否健壮
xTaskCreate(task_high_priority, "High", 256, NULL, 3, NULL);
xTaskCreate(task_medium_priority, "Med", 256, NULL, 2, NULL);
xTaskCreate(task_low_priority, "Low", 256, NULL, 1, NULL);
💡 我的经验:多任务测试时,别忘了检查堆栈溢出。我曾经遇到一个bug,某个任务堆栈只分配了128字节,结果一跑并发就栈溢出,系统随机死机。排查了整整两天才找到原因。从那以后,我每个任务都至少分配256字节起步。
测试过程中要记录的数据:
| 监控指标 | 正常范围 | 异常表现 |
|---|---|---|
| 任务切换时间 | < 10μs | 切换时间突然增大,说明调度器卡顿 |
| 任务响应延迟 | < 1ms | 高优先级任务响应延迟超过5ms,说明优先级反转 |
| CPU占用率 | 80%-95% | 占用率突然降到0%,可能系统死锁 |
| 堆栈使用率 | < 80% | 超过90%就有溢出风险 |
3.3 中断风暴测试
中断风暴测试,是CPU压力测试里最刺激的一个环节。说白了,就是模拟极端情况下,中断以极高的频率不断触发,看看系统能不能扛得住。
为什么会发生中断风暴?
- 外设故障,比如一个传感器不停地发中断信号。
- 软件bug,比如中断标志位没有清除,导致中断反复触发。
- 外部干扰,比如强电磁环境下GPIO引脚产生毛刺。
我常用的中断风暴测试方法:
// 中断风暴测试 - 使用定时器产生高频中断
void timer_interrupt_handler(void) {
// 清除中断标志
TIM->SR = ~TIM_SR_UIF;
// 模拟中断处理:做少量工作
volatile uint32_t temp = 0;
for(int i = 0; i < 10; i++) {
temp += i;
}
// 记录中断次数
interrupt_count++;
}
void start_storm_test(void) {
// 设置定时器频率为 100kHz,即每10μs触发一次中断
TIM->PSC = 72 - 1; // 72MHz时钟,预分频后为1MHz
TIM->ARR = 10 - 1; // 自动重装值,产生100kHz中断
TIM->DIER |= TIM_DIER_UIE; // 使能更新中断
TIM->CR1 |= TIM_CR1_CEN; // 启动定时器
}
🔑 关键点:中断风暴测试要关注三个指标:
- 中断响应时间:从中断触发到进入ISR的时间,不能超过系统要求。
- 中断处理时间:ISR内部执行时间,必须小于中断间隔,否则会丢失中断。
- 中断嵌套深度:如果支持中断嵌套,要测试最深能嵌套几层而不崩。
我记得有一次做工业控制项目,现场设备频繁死机。排查后发现是一个外部中断引脚没做硬件滤波,电机启动时的电磁干扰导致中断风暴。嗯,从那以后,我所有中断引脚都加上了RC滤波,软件里也做了去抖处理。
避坑指南:
- 我曾经在中断服务函数里调用了printf,结果一跑中断风暴,系统直接卡死。因为printf本身是阻塞的,而且可能触发其他中断。记住:ISR里尽量只做标志位操作,复杂逻辑放到任务里处理。
- 我曾经遇到一个芯片,中断风暴时居然把Flash里的代码都冲坏了。后来发现是电源纹波太大,导致Flash读取错误。所以,做中断风暴测试时,一定要同时监控电源质量。
最后总结一下:CPU压力测试不是走过场,它是检验系统稳定性的试金石。满负荷测试看散热和供电,多任务测试看调度和资源管理,中断风暴测试看实时性和鲁棒性。这三个维度都过了,你的系统才算真正经得起考验。