FreeRTOS 工程化要点:任务划分、优先级设计与 CPU 占用率监控
大家好我是杂烩君。今天我们来简单分享FreeRTOS任务怎么拆、优先级怎么配、CPU 占用怎么看。1. 任务划分原则1.1 单一职责一个任务只干一件事把串口接收 数据解析 指令执行 结果反馈全塞一个任务解析环节一出问题整条链路全挂而且任务执行时间拉长后会阻塞其他高优先级任务。正确做法按照职责拆成各独立任务通过队列串联某一环节异常不影响其他环节。1.2 低耦合与合理粒度任务间数据传递走队列、任务通知、事件组别直接读写全局变量。任务数量上一般中小项目控制在5~8 个比较合理——太少功能挤一起难维护太多上下文切换开销吃不消。划分流程可以按下面这个思路走1.3 轻量化单次执行控制在 10ms 以内看一下内核中空闲任务的主循环tasks.cfor(;configCONTROL_INFINITE_LOOP();){prvCheckTasksWaitingTermination();#if(configUSE_IDLE_HOOK1){vApplicationIdleHook();}#endif/* ... tickless idle, yield 逻辑 ... */}空闲任务只有在所有其他任务都阻塞时才能拿到 CPU。你的任务一跑就是几十毫秒不释放空闲任务跑不了低功耗和看门狗喂狗逻辑都会出问题。耗时操作必须拆子任务或分段执行。2. 优先级设计2.1 核心原则数字越大优先级越高这是非常多人搞反的点。FreeRTOS 中空闲任务优先级为 0是最低的/* FreeRTOS-Kernel/include/task.h */#definetskIDLE_PRIORITY((UBaseType_t)0U)优先级范围是0到configMAX_PRIORITIES - 1数字越大越先执行。分配时核心实时任务给大数字后台任务给小数字。非必要别让多个任务共用同一优先级否则触发时间片轮转增加切换开销。任务类型优先级说明故障报警10必须最快响应传感器采集8实时性要求高数据解析/指令执行6外设通信串口等4显示/按键3日志/自检1仅高于空闲任务3. CPU 占用率监控CPU 占用率是系统健康度的晴雨表建议控制在30%~70%。FreeRTOS 内核原生支持运行时统计configGENERATE_RUN_TIME_STATS每次上下文切换时自动累计每个任务的运行时间精度高、零应用层计算代码直接用就行。3.1 内核原理开启configGENERATE_RUN_TIME_STATS后内核在每次任务切换时执行以下逻辑tasks.c/* FreeRTOS-Kernel/tasks.c — 上下文切换时更新运行时统计 */#if(configGENERATE_RUN_TIME_STATS1){ulTotalRunTime[0]portGET_RUN_TIME_COUNTER_VALUE();if(ulTotalRunTime[0]ulTaskSwitchedInTime[0]){pxCurrentTCB-ulRunTimeCounter(ulTotalRunTime[0]-ulTaskSwitchedInTime[0]);}ulTaskSwitchedInTime[0]ulTotalRunTime[0];}#endif每个 TCB 里有个ulRunTimeCounter字段记录该任务累计占用 CPU 的时间。调用vTaskGetRunTimeStats()时内核遍历所有任务算出每个任务的时间占比格式化成可读字符串直接输出。你只需要做两件事配好 FreeRTOSConfig.h提供一个高精度计数器。3.2 验证代码下面是一个例子用DWT 周期计数器作为运行时统计的时间基准创建了两个不同负载的测试任务 一个监控任务串口输出统计结果。3.2.1 FreeRTOSConfig.h 需要增加的配置在你已有的FreeRTOSConfig.h中加入以下内容/* ---------- 运行时统计相关 ---------- */#defineconfigGENERATE_RUN_TIME_STATS1#defineconfigUSE_TRACE_FACILITY1#defineconfigUSE_STATS_FORMATTING_FUNCTIONS1externvoidvConfigureTimerForRunTimeStats(void);externuint32_tulGetRunTimeCounterValue(void);#defineportCONFIGURE_TIMER_FOR_RUN_TIME_STATS()vConfigureTimerForRunTimeStats()#defineportGET_RUN_TIME_COUNTER_VALUE()ulGetRunTimeCounterValue()这三个宏缺一不可configGENERATE_RUN_TIME_STATS开启统计功能configUSE_TRACE_FACILITY开启uxTaskGetSystemState()configUSE_STATS_FORMATTING_FUNCTIONS开启vTaskGetRunTimeStats()格式化输出。3.2.2 核心测试代码/*------------------------------------------------------------ * 运行时统计计数器 — DWT CYCCNT (内核自带, 不占任何外设) * * DWT 单元有一个 32 位周期计数器, * 以内核主频计数 (L431 最高 80MHz → 分辨率 12.5ns) * 32 位在 80MHz 下约 53.7 秒溢出, 但内核每次上下文切换 * 都会读取并做差值累加, 任务切换间隔远小于该值, 不影响统计 *------------------------------------------------------------*/voidvConfigureTimerForRunTimeStats(void){CoreDebug-DEMCR|CoreDebug_DEMCR_TRCENA_Msk;DWT-CYCCNT0;DWT-CTRL|DWT_CTRL_CYCCNTENA_Msk;}uint32_tulGetRunTimeCounterValue(void){returnDWT-CYCCNT;}/*------------------------------------------------------------ * 测试任务 *------------------------------------------------------------*//* 重载任务: 忙等 ~5ms 休眠 20ms, 预期占用约 20% CPU */voidTask_Heavy(void*pv){volatileuint32_ti;for(;;){for(i0;i20000;i){}/* 忙等, 模拟计算负载 */vTaskDelay(pdMS_TO_TICKS(20));}}/* 轻载任务: 几乎不占 CPU, 500ms 唤醒一次做极少工作 */voidTask_Light(void*pv){volatileuint32_tcount0;for(;;){count;vTaskDelay(pdMS_TO_TICKS(500));}}/* 监控任务: 每 3 秒输出一次各任务的运行时间统计 */voidTask_Monitor(void*pv){staticcharbuf[400];for(;;){vTaskDelay(pdMS_TO_TICKS(3000));printf(\r\n-------- Run Time Stats --------\r\n);printf(Task Abs Time %%Time\r\n);vTaskGetRunTimeStats(buf);printf(%s,buf);printf(--------------------------------\r\n);}}intmain(void){// ...xTaskCreate(Task_Heavy,Heavy,256,NULL,4,NULL);xTaskCreate(Task_Light,Light,128,NULL,3,NULL);xTaskCreate(Task_Monitor,Monitor,512,NULL,1,NULL);vTaskStartScheduler();for(;;){}}3.2.3 串口输出每 3 秒会看到类似输出Heavy任务忙等约 5ms 休眠 20ms占用约 16%符合预期。IDLE占 83% 说明系统大部分时间空闲。如果你在自己的项目里加上这个监控任务一眼就能看出哪个任务吃 CPU 最多。3.3 异常速查现象常见原因优化方向80%死循环无延时、中断过频、资源竞争激烈拆分耗时任务、降低中断频率20%延时过长、执行频率低缩短延时、充分利用 CPU波动大突发耗时操作、中断源不稳定分段执行、稳定中断源4. 总结FreeRTOS 工程落地就三件事任务划分——单一职责、轻量化、低耦合5~8 个任务为宜别把所有逻辑塞一个任务里也别拆太碎。优先级设计——数字越大优先级越高tskIDLE_PRIORITY 0是最低核心实时任务给高值后台任务给低值共享资源用xSemaphoreCreateMutex()优先级继承内核自动搞定。CPU 占用率监控——开启configGENERATE_RUN_TIME_STATS用 DWT CYCCNT 做时间基准不占外设vTaskGetRunTimeStats()直接输出每个任务的占比30%~70% 是健康区间。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2480263.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!