Z-Stack 协议剖析
基于 TI CC2530/CC2538 源码分析
Zigbee 协议栈全景图
该项目通过 OSAL (操作系统抽象层) 调度整个 Zigbee 协议栈。 从底层的 MAC 任务到顶层的用户应用任务,每一层都各司其职。
协议栈层级 (Stack Layers)
APP (用户应用层)
zclSampleSw_Init / Event Loop
ZCL
集群库 (Cluster Library)
BDB
基础设备行为
AF (应用框架层)
Endpoint & Message Dispatch
ZDO (设备对象层)
Device Discovery & Security
APS (应用支持子层)
Binding & Groups
NWK (网络层)
Routing & Mesh
MAC / PHY (硬件层)
Radio Frequency (802.15.4)
OSAL 任务调度
系统启动时按优先级初始化任务列表:
- macTaskInit
- nwk_init
- Hal_Init
- APS_Init
- ZDApp_Init
- zcl_Init
- bdb_Init
- zclSampleSw_Init (你的代码)
BDB (Base Device Behavior) – 入网与组网
Zigbee 3.0 的核心,简化了设备如何加入网络或创建网络。
bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING | ...);
协调器用它建立网络 (Formation),终端设备用它搜索网络 (Steering)。
bdb_RegisterCommissioningStatusCB(zclSampleSw_ProcessCommissioningStatus);
当入网成功或失败时,协议栈会调用这个函数,你可以在这里处理重连逻辑。
AF (Application Framework) – 发送数据
应用层最常用的接口,用于定义端点和发送无线数据包。
AF_DataRequest(&dstAddr, &epDesc, CLUSTER_ID, len, data, ...);
- dstAddr: 目标地址 (0x0000 协调器, 0xFFFF 广播)
- epDesc: 源端点描述符 (SimpleDesc)
- CLUSTER_ID: 消息类型 (如 0x8004 传感器数据)
afRegister(&sampleSw_TestEp);
告诉协议栈:发给 EndPoint 8 的消息,请转交给我的任务处理。
ZDO (设备管理)
ZDP_IEEEAddrReq: 查询设备的 64位 MAC 地址。
Device_annce: 监听设备入网广播,协调器借此发现新节点。
ZCL (集群库)
zclSampleSw_Attrs: 定义属性表(如开关状态、版本号)。
SimpleDesc: 简单描述符,告诉网络我支持哪些 Cluster (输入/输出簇)。
💡 开发小贴士
- **禁止阻塞**:不要在事件循环中使用 `while(1)` 或长延时,这会卡死整个协议栈(包括网络心跳)。
- **内存管理**:使用 `osal_mem_alloc` 和 `osal_msg_deallocate`,接收到的消息处理完必须释放内存。
- **Debug**:你的代码中封装了 `uart_printf`,这是非常有用的调试工具,建议保留。
1. 协议栈核心架构 (OSAL Task System)
在 Z-Stack 中,Zigbee 协议的各个层级(PHY, MAC, NWK, APS, ZDO, ZCL)都被实现为独立的 OSAL 任务。
- 任务初始化与事件循环: 在文件
OSAL_SampleSw.c中,可以看到协议栈各层的初始化顺序。osalInitTasks函数按优先级顺序初始化了以下关键层:macTaskInit: MAC 层(介质访问控制)。nwk_init: NWK 层(网络层,负责路由和寻址)。APS_Init: APS 层(应用支持子层,负责绑定和组播)。ZDApp_Init: ZDO 层(Zigbee 设备对象,负责设备发现和管理)。zcl_Init: ZCL 层(Zigbee 集群库,通用应用标准)。bdb_Init: BDB 层(Base Device Behavior,Zigbee 3.0 的入网行为标准)。zclSampleSw_Init: 用户应用层,即你当前的应用逻辑。
2. 应用框架层 API (AF Layer)
这是应用层发送和接收无线数据的主要接口。你的代码中大量使用了 AF 层的 API。
- 注册端点 (Endpoint Registration):
- API:
afRegister( endPointDesc_t *epDesc ) - 实现: 在
zclSampleSw_Init中,应用通过afRegister(&sampleSw_TestEp)注册了一个端点(Endpoint 8)。这告诉协议栈:发往端点 8 的消息应交给zclSampleSw_TaskID处理。
- API:
- 发送数据 (Data Request):
- API:
AF_DataRequest(...) - 实现: 在
zclSampleSw_AF_General函数中封装了此 API。它支持三种模式:afAddr16Bit: 点对点单播 (P2P)。afAddrBroadcast: 广播 (Broadcast)。afAddrGroup: 组播 (Multicast)。
- 它需要指定目标地址、Cluster ID (如
CLUSTER_P2P0x8000)、数据长度和数据负载。
- API:
- 接收数据 (Incoming Message):
- 处理机制: 当底层收到数据时,OSAL 会发送
AF_INCOMING_MSG_CMD事件。 - 实现: 在
zclSampleSw_event_loop中捕获此事件,并调用zclSampleSw_AF_RxProc处理接收到的afIncomingMSGPacket_t数据包。
- 处理机制: 当底层收到数据时,OSAL 会发送
3. 基础设备行为层 API (BDB Layer – Zigbee 3.0)
BDB 层简化了 Zigbee 网络的建立和加入过程(Commisioning)。
- 启动入网/组网:
- API:
bdb_StartCommissioning( mode ) - 实现:
- 协调器 (Coordinator): 使用
BDB_COMMISSIONING_MODE_NWK_FORMATION | BDB_COMMISSIONING_MODE_NWK_STEERING来创建网络并允许其他设备加入。 - 终端/路由 (EndDevice/Router): 使用
BDB_COMMISSIONING_MODE_NWK_STEERING来搜索并加入现有网络。
- 协调器 (Coordinator): 使用
- API:
- 入网状态回调:
- API:
bdb_RegisterCommissioningStatusCB( callback ) - 实现: 注册了
zclSampleSw_ProcessCommissioningStatus函数。当入网成功(BDB_COMMISSIONING_SUCCESS)或失败时,协议栈会回调此函数。你的代码在这里处理了断线重连逻辑。
- API:
4. Zigbee 设备对象层 API (ZDO Layer)
ZDO 负责设备在网络中的管理功能,如地址发现、节点描述符查询等。
- 地址请求:
- API:
ZDP_IEEEAddrReq(...) - 实现: 在
zclSampleSw_AF_RxProc中,协调器收到新设备的数据后,调用此函数查询该设备的 64 位 MAC 地址(IEEE Address)。
- API:
- ZDO 消息注册与处理:
- API:
ZDO_RegisterForZDOMsg(...) - 实现: 在初始化时注册了
IEEE_addr_rsp和Device_annce消息。当收到这些 ZDO 响应时,会在zclSampleSw_processZDOMgs函数中进行解析。
- API:
5. Zigbee 集群库实现 (ZCL Layer)
ZCL 定义了标准化的设备行为(如开关、调光、温湿度传感器)。
- 属性表 (Attribute Table):
- 实现: 在
zcl_samplesw_data.c中定义了zclSampleSw_Attrs数组。这包含了该设备支持的所有标准属性,例如:ZCL_CLUSTER_ID_GEN_BASIC: 基础信息(厂商名、型号)。ZCL_CLUSTER_ID_GEN_ON_OFF: 开关状态。
- 实现: 在
- 简单描述符 (Simple Descriptor):
- 实现:
zclSampleSw_SimpleDesc定义了设备支持的 Cluster ID 列表(输入和输出簇),这是其他 Zigbee 设备识别该设备功能的依据。
- 实现:
6. 网络管理与辅助 API (NWK & APS)
虽然你的应用代码主要通过 BDB 和 AF 操作,但也直接使用了部分底层 API:
- 组管理:
- API:
aps_AddGroup(...) - 实现: 初始化时调用此函数将端点加入到组 ID
0x0001,用于接收组播消息。
- API:
- 入网许可 (Permit Join):
- API:
NLME_PermitJoiningRequest(...) - 实现: 协调器调用此函数来通过 MAC 层/网络层命令允许新设备入网。
- API:
- 地址获取:
- API:
NLME_GetExtAddr(),NLME_GetShortAddr() - 实现: 用于获取自身的 64 位长地址和 16 位短地址。
- API:
总结
该仓库实现了一个基于 Z-Stack 的 Zigbee 应用,其协议交互流程如下:
- OSAL 启动并调度各层任务。
- BDB 负责将设备接入 Zigbee 网络。
- ZDO 辅助获取网络中设备的地址信息。
- ZCL 定义了设备的标准属性和描述符。
- AF 提供了应用层收发自定义传感器数据(如光照、温湿度)的通道。
