在实时操作系统中,任务调度只是系统运行机制的一部分,任务之间如何使用和等待系统资源,同样直接影响系统的运行状态。
例如,当一个任务长时间处于等待状态时,仅仅查看任务本身的信息,往往很难判断它究竟在等待什么。
如果能够直接查看资源对象的当前状态,就可以进一步回答:
-
当前资源的值是多少?
-
当前是否存在资源拥有者?
-
有多少任务正在等待?
-
哪些任务正在等待该资源?
-
是否存在来自ISR的待处理信号?
针对这些问题,HRTOS Debug提供了 Resource状态监控功能。
该模块统一分析HRTOS内部的8个Resource对象,并提供资源值、拥有者、等待任务数量、等待任务位图以及ISR Pending Signal等运行状态信息。
需要特别说明的是:
HRTOS Debug Resource模块只读取和分析内核资源状态,不修改内核数据。
一、HRTOS Resource的统一设计
HRTOS内部采用统一的Resource对象管理部分同步和通信相关机制。
Resource对象包含以下主要信息:
Resource
│
├── value
├── owner
├── wait_cnt
├── wait_mask
└── pending_signal
这些Resource可以用于:
Semaphore
Mutex
Event
Message Queue Wait
因此,Debug模块并不需要针对每一种同步机制分别设计一套监控接口,而是直接读取统一的Resource对象。
整体关系可以表示为:
HRTOS Resource
│
┌────────────┼────────────┐
│ │ │
Semaphore Mutex Event
│ │
└──── Message Queue Wait ┘
│
▼
HRTOS Debug
│
┌────────────┼────────────┐
│ │ │
Value Owner Waiters
│
Pending Signal
这种设计可以让Debug层与内核资源机制保持一致。
二、Resource对象
Debug模块通过以下方式访问HRTOS内部的Resource数组:
extern volatile OS_RESOURCE xdata OS_RES[
HRTOS_DEBUG_RESOURCE_MAX];
同时定义:
#define HRTOS_DEBUG_RESOURCE_MAX 8
#define HRTOS_DEBUG_INVALID_ID 0xFF
因此当前Debug模块监控:
Resource 0
Resource 1
Resource 2
Resource 3
Resource 4
Resource 5
Resource 6
Resource 7
共8个Resource对象。
每个Resource都有自己的运行状态。
三、Resource的五项核心信息
HRTOS Debug主要提供五类信息。
1. Resource Value
value
表示当前Resource的资源值。
对于不同类型的Resource,其具体含义由内核使用方式决定。
Debug模块不改变这个值,只负责读取当前状态。
2. Resource Owner
owner
表示当前Resource的拥有者。
这个字段对于Mutex等具有所有者概念的资源尤其有价值。
例如:
Resource 2
Owner : Task 5
可以直接知道当前资源由Task 5持有。
如果返回:
HRTOS_DEBUG_INVALID_ID
则可以表示当前没有有效的Owner。
3. Wait Count
wait_cnt
表示当前正在等待该Resource的任务数量。
例如:
Resource 3
Wait Count : 4
说明当前有4个任务处于该Resource的等待状态。
这对于分析任务阻塞非常有帮助。
4. Wait Mask
除了等待任务数量之外,HRTOS Debug还提供:
wait_mask
用于记录具体哪些任务正在等待该Resource。
HRTOS当前拥有16个普通任务,因此可以使用一个16位整数表示任务等待关系:
bit0 → Task 0
bit1 → Task 1
bit2 → Task 2
…
bit15 → Task 15
例如:
wait_mask = 0x002A
对应的二进制位中,可以直接分析出具体处于等待状态的任务。
这相比单独提供:
Wait Count = 3
提供了更多信息。
因为:
Wait Count告诉我们“有多少任务在等待”,Wait Mask则告诉我们“哪些任务在等待”。
5. Pending Signal
Resource还提供:
pending_signal
用于记录来自ISR的待处理信号计数。
这对于中断与任务之间的资源交互分析非常有意义。
例如:
ISR
│
├── 产生信号
│
▼
Resource
│
└── pending_signal
Debug模块可以直接读取当前Pending Signal状态。
四、读取单个Resource
最基础的接口是:
unsigned char HRTOS_DEBUG_Resource_Get(
unsigned char id,
HRTOS_DEBUG_RESOURCE_INFO xdata *info)
调用时传入Resource编号和输出结构体地址。
首先进行ID检查:
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 1;
}
当前有效ID范围:
0 ~ 7
如果超过范围,则直接返回错误。
随后检查输出指针:
if (info == 0)
{
return 2;
}
避免向无效地址写入数据。
五、Resource信息复制
参数检查完成后,Debug模块直接从内核Resource对象读取状态:
info->id =
id;
info->value =
OS_RES[id].value;
info->owner =
OS_RES[id].owner;
info->wait_cnt =
OS_RES[id].wait_cnt;
info->wait_mask =
OS_RES[id].wait_mask;
info->pending_signal =
OS_RES[id].pending_signal;
整个过程实际上就是:
OS_RES[id]
│
├── value
├── owner
├── wait_cnt
├── wait_mask
└── pending_signal
│
▼
HRTOS_DEBUG_RESOURCE_INFO
Debug模块只负责读取和复制。
六、获取Resource等待任务数量
如果应用程序只关心当前等待任务数量,可以直接使用:
unsigned char HRTOS_DEBUG_Resource_GetWaitCount(
unsigned char id)
例如:
unsigned char count;
count = HRTOS_DEBUG_Resource_GetWaitCount(2);
返回:
0 ~ 16
这样就不需要读取完整的Resource结构。
七、获取等待任务位图
如果需要知道具体哪些任务正在等待,可以使用:
unsigned int HRTOS_DEBUG_Resource_GetWaitMask(
unsigned char id)
例如:
unsigned int mask;
mask = HRTOS_DEBUG_Resource_GetWaitMask(2);
然后根据对应bit判断任务状态。
结构如下:
16 bit Wait Mask
15 8 7 0
┌────────────────────┬────────────────────┐
│ Task 15 … Task 8 │ Task 7 … Task 0 │
└────────────────────┴────────────────────┘
因此一个16位变量即可表达全部16个普通任务的等待关系。
对于8051这种资源受限的平台,这种设计非常直接。
八、获取Resource Owner
对于需要关注资源所有者的场景,可以使用:
unsigned char HRTOS_DEBUG_Resource_GetOwner(
unsigned char id)
例如:
unsigned char owner;
owner = HRTOS_DEBUG_Resource_GetOwner(2);
如果Resource存在有效拥有者,则返回对应Task ID。
如果ID无效:
return HRTOS_DEBUG_INVALID_ID;
其中:
#define HRTOS_DEBUG_INVALID_ID 0xFF
用于区分正常Task ID和错误状态。
九、获取Resource Value
如果只需要查询资源当前值,可以使用:
unsigned char HRTOS_DEBUG_Resource_GetValue(
unsigned char id)
例如:
unsigned char value;
value = HRTOS_DEBUG_Resource_GetValue(0);
这种接口适合Shell或者Debug界面进行单项查询。
十、获取ISR Pending Signal
对于需要分析中断与资源交互的场景,可以使用:
unsigned char HRTOS_DEBUG_Resource_GetPendingSignal(
unsigned char id)
例如:
unsigned char pending;
pending =
HRTOS_DEBUG_Resource_GetPendingSignal(1);
通过该值可以观察Resource当前是否存在来自ISR的待处理信号。
这样就能够进一步分析:
外部事件
│
▼
ISR
│
▼
Resource
│
▼
Pending Signal
│
▼
任务处理
对于实时系统中的中断—任务协作分析,这类信息具有实际意义。
十一、一次获取全部8个Resource
如果Debug界面需要显示完整的Resource状态,可以使用:
unsigned char HRTOS_DEBUG_Resource_GetAll(
HRTOS_DEBUG_RESOURCE_INFO xdata *info)
该函数一次性读取全部8个Resource。
核心代码:
for (i = 0; i < HRTOS_DEBUG_RESOURCE_MAX; i++)
{
info[i].id =
i;
info[i].value =
OS_RES[i].value;
info[i].owner =
OS_RES[i].owner;
info[i].wait_cnt =
OS_RES[i].wait_cnt;
info[i].wait_mask =
OS_RES[i].wait_mask;
info[i].pending_signal =
OS_RES[i].pending_signal;
}
调用后,输出数组就保存了完整的Resource状态。
可以进一步用于:
Shell
Debug Monitor
串口输出
系统状态分析
故障定位
十二、为什么采用“只读”设计
Resource Debug模块有一个非常重要的原则:
Debug模块只观察系统,不干预系统。
也就是说,Debug层不会修改:
OS_RES[]
中的任何内核状态。
它只执行:
读取
↓
复制
↓
分析
↓
显示
而不是:
读取
↓
修改
↓
影响调度
对于实时操作系统来说,这一点非常重要。
Debug功能本身的存在,不应该改变被调试系统的资源状态。
因此,HRTOS Debug与HRTOS内核之间可以保持比较清晰的边界:
┌─────────────────────────┐
│ HRTOS Kernel │
│ │
│ Scheduler / Resource │
│ Task / ISR / IPC │
└────────────┬────────────┘
│
Read Only
│
▼
┌─────────────────────────┐
│ HRTOS Debug │
│ │
│ Resource Monitor │
│ Task Monitor │
│ CPU Usage │
│ Stack Monitor │
└─────────────────────────┘
十三、Resource Debug可以解决什么问题
假设某个任务长期处于等待状态。
仅仅查看任务状态:
Task 5 : WAIT
信息是不完整的。
进一步查看Resource:
Resource 2
Value : …
Owner : Task 3
Wait Count : 4
Wait Mask : …
Pending Signal : …
就能够进一步判断:
Task 5
│
▼
正在等待 Resource 2
│
├── 当前Owner = Task 3
├── 还有其他任务等待
└── 是否存在Pending Signal
这样,Debug就从“查看任务状态”进一步进入了:
分析任务为什么处于当前状态。
这也是系统级Debug工具的重要价值。
十四、Resource与任务监控结合
如果进一步把Resource Monitor与Task Monitor结合起来,可以形成更加完整的分析链。
例如:
Task Monitor
│
▼
发现 Task 5 WAIT
│
▼
Resource Monitor
│
▼
找到 Resource 2
│
├── Owner
├── Wait Count
├── Wait Mask
└── Pending Signal
│
▼
进一步分析阻塞原因
再结合CPU Usage:
CPU Usage
│
▼
系统负载异常
│
▼
Task Monitor
│
▼
Resource Monitor
│
▼
定位任务与资源关系
这样Debug功能就形成了从:
系统
↓
任务
↓
资源
逐层深入的分析能力。
十五、完整核心代码
Resource Debug模块完整实现如下:
#include "HRTOS_Debug.h"
#define HRTOS_DEBUG_RESOURCE_MAX 8
#define HRTOS_DEBUG_INVALID_ID 0xFF
extern volatile OS_RESOURCE xdata OS_RES[
HRTOS_DEBUG_RESOURCE_MAX];
unsigned char HRTOS_DEBUG_Resource_Get(
unsigned char id,
HRTOS_DEBUG_RESOURCE_INFO xdata *info)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 1;
}
if (info == 0)
{
return 2;
}
info->id =
id;
info->value =
OS_RES[id].value;
info->owner =
OS_RES[id].owner;
info->wait_cnt =
OS_RES[id].wait_cnt;
info->wait_mask =
OS_RES[id].wait_mask;
info->pending_signal =
OS_RES[id].pending_signal;
return 0;
}
unsigned char HRTOS_DEBUG_Resource_GetWaitCount(
unsigned char id)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 0;
}
return OS_RES[id].wait_cnt;
}
unsigned int HRTOS_DEBUG_Resource_GetWaitMask(
unsigned char id)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 0;
}
return OS_RES[id].wait_mask;
}
unsigned char HRTOS_DEBUG_Resource_GetOwner(
unsigned char id)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return HRTOS_DEBUG_INVALID_ID;
}
return OS_RES[id].owner;
}
unsigned char HRTOS_DEBUG_Resource_GetValue(
unsigned char id)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 0;
}
return OS_RES[id].value;
}
unsigned char HRTOS_DEBUG_Resource_GetPendingSignal(
unsigned char id)
{
if (id >= HRTOS_DEBUG_RESOURCE_MAX)
{
return 0;
}
return OS_RES[id].pending_signal;
}
unsigned char HRTOS_DEBUG_Resource_GetAll(
HRTOS_DEBUG_RESOURCE_INFO xdata *info)
{
unsigned char i;
if (info == 0)
{
return 1;
}
for (i = 0; i < HRTOS_DEBUG_RESOURCE_MAX; i++)
{
info[i].id =
i;
info[i].value =
OS_RES[i].value;
info[i].owner =
OS_RES[i].owner;
info[i].wait_cnt =
OS_RES[i].wait_cnt;
info[i].wait_mask =
OS_RES[i].wait_mask;
info[i].pending_signal =
OS_RES[i].pending_signal;
}
return 0;
}
十六、总结
HRTOS Debug Resource模块通过统一的Resource对象,对HRTOS内部资源运行状态进行集中监控。
目前可以获取:
Resource Value
Resource Owner
Wait Count
Wait Mask
Pending Signal
其中:
Wait Count
用于了解当前有多少任务等待资源;
Wait Mask
用于进一步确定具体哪些任务正在等待;
Owner
用于分析资源当前拥有者;
Pending Signal
用于观察ISR与Resource之间的信号状态。
整个模块遵循:
只读内核状态,不修改内核数据。
因此它可以作为HRTOS Debug体系中的一个独立观察层,为任务状态分析、资源等待分析以及中断—任务协作分析提供基础数据。
对于资源有限的8051实时系统而言,Debug并不一定需要复杂的调试器接口。
能够直接看到:
任务在做什么
资源在做什么
谁在等待
谁拥有资源
系统有多忙
就已经能够解决相当一部分实际开发中的定位问题。
这也是HRTOS Debug希望提供的核心能力:
让实时系统内部的运行状态变得可观察、可分析。
网硕互联帮助中心




评论前必须登录!
注册