ZigBee学习之37——osalInitTasks()分析
此函数完成了任务ID的分配,以及所有任务的初始化,如果我们要加入自己的应用必须在这里加入自己的任务初始化函数,以使系统可以自动为任务分配一个ID号。如果是想要自己创建一个应用,那么必须首先实现两个东西,一是任务回调函数队列,另一个是系统任务初始化及ID分配。任务队列是一个pTaskEventHandlerFn结构的数组,只要把每个任务相关的回调函数按初始化队列中的顺序填到数组中就可以了,他们的实现一般是写在自己的应用源码里面。介绍一个例子(SimpleApp):
const pTaskEventHandlerFn tasksArr[] = { macEventLoop, nwk_event_loop, Hal_ProcessEvent, #if defined( MT_TASK ) MT_ProcessEvent, #endif
APS_event_loop, ZDApp_event_loop,
SAPI_ProcessEvent };
void osalInitTasks( void ) {
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID++ ); nwk_init( taskID++ ); Hal_Init( taskID++ ); #if defined( MT_TASK ) MT_TaskInit( taskID++ ); #endif
APS_Init( taskID++ ); ZDApp_Init( taskID++ ); SAPI_Init( taskID ); }
注意这里两个实体里面的顺序要一一对应!
macTaskInit( taskID++ ),nwk_init( taskID++ ),APS_Init( taskID++ )定义在mac_api.h,nwk.h,APS.h中,但没有找到其实现,可能被打包在链接库文件里面了。
void Hal_Init( uint8 task_id ) {
/*将系统分配的任务的ID传给变量*/
Hal_TaskID = task_id; }
//开始器件的启动【ZDApp.c】
void ZDApp_Init( byte task_id ) {
uint8 capabilities;
//保存系统分配的任务ID ZDAppTaskID = task_id;
//初始化ZDO全局的短地址,并配置成无效的一个地址 ZDAppNwkAddr.addrMode = Addr16Bit;
ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;
// ZDAppNwkAddr为一个地址数据结构:addrMode只有几种: AddrNotPresent = 0, AddrGroup = 1, Addr16Bit = 2, Addr64Bit = 3, AddrBroadcast = 15
typedef struct { union {
uint16 shortAddr; ZLongAddr_t extAddr; } addr;
byte addrMode; } zAddrType_t;
(void)NLME_GetExtAddr(); //这是个ZstackAPI,返回指向此器件64位地址的指针
//检查\,如果启动的时候按着SW1,此函数就会设置设备的状态为:DEV_HOLD
ZDAppCheckForHoldKey();
//初始化ZDO物件,并且设置设备 ZDO_Init();
//【ZDObject.c】 void ZDO_Init( void ) {
#if defined ( REFLECTOR )
//如果器件定义的是“反射器”则需要定义个路由的设备结构,REFLECTOR是一个编译选项,如果定义了这个编译选项则使用“源绑定”,源绑定的定义有这样一句话In the Zigbee 2006 release,the binding mechanism is implemented in all devices and is called source binding(在Zigbee2006中,绑定机制在所有的设备中实现,这就叫做源绑定),如果使用源绑定则绑表是存放在源设备中的,这样就不用为找绑定入口而先向协调器提交绑定请求,但是方面又增大了源节点的开销,因为要为保存绑定表而开辟一段静态内存。默认是不使用源绑定。
ZDO_EDBind = NULL; #endif
//设置创建设备的类型 ZDODeviceSetup();
//根据设置的编译选项来调用不同的网络层管理函数 // ZDO_COORDINATOR:设备作为协调器
// SOFT_START:如果没有协调器则设备以协调器启动,否则以路由器启动
//这里面的几个函数都做成了静态库了看不到源码!看来TI的所谓开放也不是完全开放
static void ZDODeviceSetup( void ) {
#if defined( ZDO_COORDINATOR ) NLME_CoordinatorInit(); #endif
#if defined ( REFLECTOR )
#if defined ( ZDO_COORDINATOR )
APS_ReflectorInit( APS_REFLECTOR_PUBLIC ); #else
APS_ReflectorInit( APS_REFLECTOR_PRIVATE ); #endif #endif
#if !defined( ZDO_COORDINATOR ) || defined( SOFT_START )
NLME_DeviceJoiningInit(); #endif }
}
// 向AF层注册endpoint(终端)
afRegister( (endPointDesc_t *)&ZDApp_epDesc );
endPointDesc_t ZDApp_epDesc = { ZDO_EP,
//0,ZDO为终端0 &ZDAppTaskID, //指向应用任务号
(SimpleDescriptionFormat_t *)NULL,
// 终端的简单描述,No Simple description for ZDO (afNetworkLatencyReq_t)0 // No Network Latency req };
#if defined( ZDO_USERDESC_RESPONSE ) ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
//从NIB中读取属性
NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);
//设置设备能处理的广播消息
NLME_SetBroadcastFilter( capabilities );
//根据设备状态启动设备,如果不是DEV_HOLD则启动ZDO设备,否则闪烁LED1 if ( devState != DEV_HOLD ) {
ZDOInitDevice( 0 );
//启动网络中的设备,在这个函数中会调用ZDApp_NetworkInit()来启动网络,并发送ZDO_NETWORK_INIT事件,当ZDO事件循环ZDApp_event_loop()接收到这个事件后会执行ZDO_StartDevice()来启动设备 } else {
// Blink LED to indicate HOLD_START