很多人第一次看到 8051 RTOS 的 Debug 模块,可能都会有一个疑问:
8051 本身资源就这么少,为什么还要专门做 Debug?
RAM 不够用,XDATA 不够用,代码空间也有限。
这个时候不应该尽量把程序做小吗?
为什么还要增加 Debug、Shell、内存检测这些东西?
实际上,我认为对于一个真正需要长期维护的 8051 RTOS 来说,Debug 并不是多余的功能。
恰恰相反:
8051 资源越有限,系统出现问题以后,越需要有效的诊断工具。
一、没有 Debug,系统出了问题怎么办?
假设一个 8051 RTOS 出现了一个问题:
程序偶尔卡住
这个时候最直接的办法可能是:
printf("error\\r\\n");
或者:
printf("task=%d\\r\\n", id);
然后重新编译、下载、测试。
如果问题再次出现,再增加几个变量。
再编译。
再下载。
再测试。
慢慢增加打印信息。
这种方法当然可以使用。
但当系统越来越复杂以后,就会发现:
单纯靠 printf 调试,会越来越困难。
因为你真正想知道的可能不是一个变量,而是整个系统当前处于什么状态。
二、RTOS真正需要观察的是“系统状态”
例如一个任务突然没有运行了。
你可能需要知道:
任务 ID
任务优先级
任务当前状态
任务是否等待
等待什么资源
任务栈使用情况
如果是一个资源问题,还可能需要知道:
哪个资源被占用?
哪个任务持有资源?
有没有任务正在等待?
如果是消息通信问题,又需要知道:
消息队列当前有多少数据?
队列最大容量是多少?
是否已经接近满载?
是否存在长期没有消费的消息?
这些信息组合起来以后,才真正接近:
系统为什么会出现这个问题?
三、所以 HRTOS Debug 不是简单的“打印几个变量”
HRTOS 的 Debug 模块,本质上希望解决的是:
让开发者能够观察 RTOS 当前的运行状态。
目前 HRTOS Debug 已经逐步覆盖几个比较重要的部分。
例如:
CPU
可以观察系统 CPU 使用情况。
如果一个系统:
CPU = 100%
那么就需要进一步判断:
-
是不是任务负载太高?
-
是不是某个任务一直占用 CPU?
-
是不是系统陷入了异常循环?
如果 CPU 长时间非常低,也可以进一步分析:
-
系统是不是大量处于等待状态?
-
是否存在资源利用不足?
四、Task:系统里到底有哪些任务?
对于 RTOS 来说,任务是最核心的运行对象之一。
Debug 可以帮助观察:
Task ID
Priority
State
Wait
Stack
Delete
例如:
Task 0 READY
Task 1 WAIT
Task 2 BLOCK
Task 3 READY
这时候如果系统表现异常,就可以进一步判断:
到底是哪个任务没有运行?
而不是只能对着代码猜。
五、Stack:8051尤其需要关注栈
8051 的栈资源非常宝贵。
一个任务到底用了多少栈?
还剩多少?
有没有接近危险范围?
这些都是非常值得关注的数据。
例如:
Task 0
Requested : 14
Used : 71%
Free : 4
这样的信息比单纯知道:
程序没死
有价值很多。
因为系统可能现在还能正常运行,但栈空间已经非常紧张。
如果后面再增加一个函数调用,或者增加一次中断嵌套,就可能出现问题。
六、Resource:为什么任务一直在等待?
RTOS 里面经常会遇到这种情况:
“这个任务为什么不运行?”
如果只是看代码,很可能需要一点一点分析。
但是如果 Debug 能直接告诉你:
Task 2
WAIT
Resource 3
那么排查方向就非常明确了。
进一步检查:
Resource 3
Owner : Task 1
Wait : Task 2
那么资源竞争关系就更加清楚。
这就是 RTOS Debug 的意义:
不是代替开发者思考,而是把开发者需要的信息直接提供出来。
七、MSGQ:消息队列也需要观察
消息队列也是一样。
假设一个系统突然出现:
“通信偶尔不正常。”
那么可能存在很多原因:
-
生产者太快
-
消费者太慢
-
队列满了
-
队列没有及时清空
-
任务没有及时运行
-
消息处理存在异常
如果能够观察:
Queue 0 : 70
Queue 1 : 199
Queue 2 : 18
Queue 3 : 15
至少可以快速知道:
当前消息队列到底处于什么状态。
这比盲目修改代码有效得多。
八、有人可能会说:这些东西直接打印出来不就行了吗?
当然可以。
对于一个非常简单的 8051 程序:
main()
↓
while(1)
↓
几个函数
几个串口打印基本就可以解决大部分问题。
但是 RTOS 不一样。
当系统里面出现:
多个任务
+
中断
+
抢占
+
信号量
+
互斥锁
+
消息队列
+
任务删除
+
延时
系统已经不是简单的顺序程序了。
这个时候:
开发者需要观察的是系统,而不是某一个变量。
这也是为什么 RTOS 会逐渐需要自己的 Debug 工具。
九、8051资源有限,所以 Debug 也必须“克制”
当然,我并不是认为:
Debug 功能越多越好。
这同样不符合 8051 的实际情况。
8051 的资源非常有限,所以 Debug 本身也必须考虑资源占用。
因此 HRTOS 的思路并不是把一个大型 PC 调试系统硬塞进 8051。
而是:
只提供真正有价值的运行时信息。
例如:
CPU
Task
Stack
Resource
MSGQ
Memory
这些信息直接服务于 RTOS 的运行状态诊断。
同时 Debug 作为可选组件,不需要的时候可以不使用。
这样就能够在:
资源占用
↕
诊断能力
之间取得平衡。
十、Debug的价值,很多时候是在“出问题以后”体现出来的
这是我觉得最重要的一点。
一个系统正常运行的时候:
Debug 看起来可能没有什么存在感。
但是系统一旦出现:
偶发死机
偶发复位
任务不运行
资源长期等待
消息队列异常
CPU异常
栈空间不足
Debug 的价值马上就体现出来了。
因为这时候开发者最需要的不是:
“再运行一次看看。”
而是:
“现在系统到底是什么状态?”
十一、这次 XDATA 问题也让我更加重视这一点
最近 HRTOS 测试过程中,我就遇到了一个比较典型的问题:
部分 51 开发板重新下载程序以后,XDATA 中可能存在之前的数据没有清零的情况。
如果系统出现异常,而没有相应的诊断工具,就很容易陷入:
怀疑内核
↓
修改代码
↓
重新编译
↓
重新下载
↓
继续测试
↓
还是异常
然后不断循环。
如果有更加完善的内存检测和运行状态诊断工具,就能够更快地把问题拆分成:
软件问题?
硬件问题?
内存问题?
资源问题?
任务问题?
运行环境问题?
这也是 HRTOS 后续继续增加内存检测工具的原因之一。
十二、Debug不是RTOS的负担,而是工程能力的一部分
我现在越来越倾向于把一个完整的 8051 RTOS 理解成几个部分:
HRTOS
│
┌─────────┼─────────┐
↓ ↓ ↓
Kernel Tools Ecosystem
│ │ │
调度 Debug Drivers
中断 Shell Examples
资源 Memory Documentation
任务 Test Hardware
Kernel 负责:
让系统正确运行。
Debug 负责:
让开发者知道系统正在发生什么。
测试工具负责:
让开发者验证系统是否可靠。
驱动、示例和文档负责:
让别人能够真正使用这个系统。
它们并不是互相冲突的。
十三、一个真正长期维护的 RTOS,需要的不只是内核
以前做一个 8051 RTOS,可能觉得:
“把调度器写出来,就已经完成了。”
但随着系统不断发展,我越来越觉得:
调度器只是开始。
一个真正长期维护的系统,还需要:
Kernel
API
Shell
Debug
Drivers
Examples
Tests
Memory Tools
Documentation
Hardware Verification
这些东西共同组成一个完整的软件体系。
其中 Debug 看起来只是一个外围模块,但它承担的是:
把系统内部状态暴露给开发者。
这对于一个长期维护的系统非常重要。
写在最后
所以,回到最开始的问题:
8051 只有这么点资源,HRTOS 为什么还要做 Debug?
我的答案是:
正因为 8051 资源有限、系统复杂度又不能无限降低,所以更加需要有效的诊断手段。
Debug 并不是为了让 HRTOS 看起来“功能更多”。
而是为了在真正出现问题的时候,能够更快回答几个最重要的问题:
系统现在怎么样?
哪个任务有问题?
哪个资源有问题?
栈还剩多少?
消息队列怎么样?
CPU负载怎么样?
到底是软件还是运行环境出了问题?
如果这些问题能够更快得到答案,那么 Debug 本身就有价值。
未来 HRTOS 也会继续完善:
Debug、Shell、内存检测、测试工具以及更多工程化组件。
8051 的资源确实有限。
但我认为:
资源有限,不应该成为放弃工程化的理由。
在有限资源里面,把真正有价值的东西做好,这可能才是 8051 RTOS 更值得做的事情。
HRTOS,持续维护,持续完善。
网硕互联帮助中心






评论前必须登录!
注册