资讯动态

RT-Thread 第3课时:时钟管理、软件定时器 内存管理

发布时间:2026/10/21 12:28:23 来源:尧图企业网站定制
一、课时目标理解 RT-Thread 系统时钟 Tick 与节拍机制熟练使用软件定时器单次定时器 / 周期定时器掌握系统延时原理ms 级延时底层怎么走精通动态堆内存malloc/free、内存池原理与实操学会用 FinSH 排查内存泄漏、栈溢出二、第一部分RT-Thread 时钟管理核心2.1 什么是系统时钟节拍TickRT-Thread 内核靠硬件定时器 SysTick产生周期性中断这个中断就是时钟节拍默认1000Hz → 1Tick 1ms所有延时、线程挂起、定时器计时全靠 Tick 累加判断核心逻辑系统维护全局计数器rt_tick每进一次 SysTick 中断 1线程延时 / 定时器到期对比当前rt_tick差值触发动作。2.2 常用延时函数底层区别// 1.线程延时会挂起线程让出CPU推荐 void rt_thread_mdelay(rt_int32_t ms); // 2.硬循环延时空跑霸占CPU禁止RTOS里用 void rt_hw_us_delay(rt_uint32_t us);✅ 工程规范业务代码一律用rt_thread_mdelay不裸跑死循环。2.3 FinSH 查看系统时钟串口输入tick可实时查看当前系统总节拍数验证时钟正常跑。三、第二部分软件定时器实操重点必考3.1 软件定时器分类单次定时器倒计时结束执行 1 次自动停止周期定时器倒计时循环触发一直跑直到手动停止运行特点默认在定时器线程里回调优先级固定回调函数要精简不能写长延时、不能死循环3.2 定时器核心 API// 创建动态定时器 rt_timer_t rt_timer_create(const char *name, void (*timeout)(void *param), void *parameter, rt_tick_t time, rt_uint8_t flag); // 启动定时器 rt_err_t rt_timer_start(rt_timer_t timer); // 停止定时器 rt_err_t rt_timer_stop(rt_timer_t timer); // 删除定时器 rt_err_t rt_timer_delete(rt_timer_t timer);flag 宏RT_TIMER_FLAG_ONE_SHOT单次RT_TIMER_FLAG_PERIODIC周期3.3 实战 1单次定时器延时触发需求开机 3 秒后打印一次提示只执行一次#include rtthread.h // 定时器回调函数 void timer_once_cb(void *param) { rt_kprintf(【单次定时器】3秒时间到执行一次\r\n); } int main(void) { // 创建单次定时器3000ms rt_timer_t t1 rt_timer_create(once_t, timer_once_cb, RT_NULL, 3000, RT_TIMER_FLAG_ONE_SHOT); if(t1 ! RT_NULL) { rt_timer_start(t1); rt_kprintf(单次定时器已启动等待3秒...\r\n); } return 0; }3.4 实战 2周期定时器定时巡检需求每隔 1 秒自动打印心跳日志#include rtthread.h void timer_period_cb(void *param) { rt_kprintf(【周期定时器】心跳上报系统运行正常\r\n); } int main(void) { rt_timer_t t2 rt_timer_create(period_t, timer_period_cb, RT_NULL, 1000, RT_TIMER_FLAG_PERIODIC); if(t2 ! RT_NULL) { rt_timer_start(t2); rt_kprintf(周期心跳定时器已启动\r\n); } return 0; }3.5 定时器避坑指南回调函数禁止rt_thread_mdelay长延时回调里尽量只做标记、发信号量、丢消息队列频繁创建不删除 → 内存泄漏四、第三部分RT-Thread 内存管理4.1 两种内存方案对比表格类型特点适用场景堆内存rt_malloc随意大小、易碎片不定长数据、临时缓存内存池固定块、无碎片、分配快报文、帧数据、频繁申请释放4.2 堆内存常用 API// 分配内存 void *rt_malloc(rt_size_t size); // 释放内存 void rt_free(void *ptr); // 重新调整大小 void *rt_realloc(void *ptr, rt_size_t size);实战动态内存申请与释放#include rtthread.h int main(void) { // 申请128字节 char *buf rt_malloc(128); if(buf ! RT_NULL) { rt_kprintf(内存申请成功\r\n); rt_sprintf(buf,Hello RT-Thread Memory); rt_kprintf(内容%s\r\n,buf); // 必须释放否则泄漏 rt_free(buf); buf RT_NULL; } return 0; }4.3 内存池原理 实操内存池提前开好一堆固定大小内存块拿块、还块极速永不碎片。核心场景MQTT 报文、串口帧、传感器数据帧。简易流程代码创建内存池 → 2. 分配块 → 3. 使用 →4. 归还块4.4 FinSH 内存排查命令必会free # 查看整体堆内存使用、剩余 list_mem # 查看内存分布、碎片情况排查三板斧长期运行内存持续上涨 → 内存泄漏剩余内存多但申请失败 → 内存碎片五、重难点思维导图总结背诵系统所有延时 / 计时底层依赖SysTick 时钟节拍mdelay是线程挂起空循环延时是大忌软件定时器分单次 / 周期回调函数必须轻量化动态堆灵活但怕泄漏、怕碎片内存池固定块、高性能上线项目频繁收发数据优先用内存池少用裸 malloc六、课后作业写一个工程周期定时器 5 秒触发一次通过信号量唤醒采集线程模拟内存泄漏只 malloc 不 free用free命令观察内存变化用内存池实现连续申请 / 释放 10 次固定数据块观察稳定性如果觉得本文对你有帮助欢迎点赞收藏关注后续会持续更新Python新手实战教程陪你从入门到精通日常深耕嵌入式、物联网、协议开发相关技术有技术答疑、项目合作、毕设指导需求均可私信私聊

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑