- osal 启动流程
osal
流程图
![](https://images0.cnblogs.com/blog/665192/201411/242010065743980.jpg)
协调器工作流程
![](https://images0.cnblogs.com/blog/665192/201411/242010085435177.jpg)
终端器工作流程
- z-stack中事件和任务的事件处理函数是如何联系的??
![](https://images0.cnblogs.com/blog/665192/201411/242010156995159.jpg)
zigbee协议栈中的三个重要的变量:
tasksCnt:任务的总个数
tasksEvents:指针变量,指向了事件表的首地址
tasksArr:数组(如下代码定义的),数组的每一项都是一个函数指针,指向了事件处理函数
const pTaskEventHandlerFn tasksArr[]={
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SampleApp_ProcessEvent
};
- Z-stack的osal初始化与轮询操作原理介绍
osal_start_system轮询函数:(当然在进入这个函数之前要对系统进行初始化,初始化的目的主要是将所以任务的事件初始化为0)
void osal_start_system(void)
{
#if !defined ( ZBIT ) && !defined ( UBIT )
for(;;)// Forever Loop
#endif
{
uint8 idx =0;
osalTimeUpdate();
Hal_ProcessPoll();// This replaces MT_SerialPoll() and osal_check_timer().
do{
if(tasksEvents[idx])// Task is highest priority that is ready.
{
break;
}
}while(++idx < tasksCnt);
if(idx < tasksCnt)
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx]=0;// Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
events =(tasksArr[idx])( idx, events );//函数指针,调用相应的事件函数处理,
结合上面图一HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx]|= events;// Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
#if defined( POWER_SAVING )
else// Complete pass through all task events with no activity?
{
osal_pwrmgr_powerconserve();// Put the processor/system into sleep
}
#endif
}
}
13-17行:循环查看事件表是否有事件发生(有就不为零,后跳出循环《可以结合上面图一来理解》)
25行 :读取该事件。
29行 :调用事件处理函数处理
- Z-stack sample applications 部分解析(from Z-Stack Sample Applications.pdf)
- Task Initialization(任务初始化)
voidSampleApp_Init(uint8 task_id )
{
SampleApp_TaskID= task_id;
SampleApp_NwkState= DEV_INIT;
SampleApp_TransID=0;//发送数据包的序号,在zigbee协议栈中,每发送一个数据包,该发送序号自动加1.作用:接收端来计算丢包率。
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main()
#if defined ( BUILD_ALL_DEVICES )
// The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START
// We are looking at a jumper (defined in SampleAppHw.c) to be jumpered
// together - if they are - we will start up a coordinator. Otherwise,
// the device will start as a router.
if( readCoordinatorJumper())
zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
else
zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif// BUILD_ALL_DEVICES
#if defined ( HOLD_AUTO_START )
// HOLD_AUTO_START is a compile option that will surpress ZDApp
// from starting the device and wait for the application to
// start the device.
ZDOInitDevice(0);
#endif
// Setup for the periodic message's destination address
// Broadcast to everyone
SampleApp_Periodic_DstAddr.addrMode =(afAddrMode_t)AddrBroadcast;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr =0xFFFF;
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode =(afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id =&SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
=(SimpleDescriptionFormat_t*)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister(&SampleApp_epDesc);
// Register for all key events - This app will handle all key events
RegisterForKeys(SampleApp_TaskID);
// By default, all devices start out in Group 1
SampleApp_Group.ID =0x0001;
osal_memcpy(SampleApp_Group.name,"Group 1",7);
aps_AddGroup( SAMPLEAPP_ENDPOINT,&SampleApp_Group);
#if defined ( LCD_SUPPORTED )
HalLcdWriteString("SampleApp", HAL_LCD_LINE_1 );
#endif
}
代码3-38:初始化本地变量与应用程序对象等;
代码41-51:将应用程序对象注册到AF层(
afRegister
(
&
SampleApp_epDesc
)
);登记注册到OSAL与HAL系统服务中(
RegisterForKeys
(
SampleApp_TaskID
);
)。只有注册后才可以使用OSAL提供的系统服务。
2.
Task Event Handler(任务处理)
uint16SampleApp_ProcessEvent(uint8 task_id,uint16 events )
{
afIncomingMSGPacket_t*MSGpkt;
(void)task_id;// Intentionally unreferenced parameter
if( events & SYS_EVENT_MSG )
{
MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(SampleApp_TaskID);//从消息队列上接收消息
while(MSGpkt)
{
switch(MSGpkt->hdr.event )
{
// Received when a key is pressed
case KEY_CHANGE:
SampleApp_HandleKeys(((keyChange_t*)MSGpkt)->state,((keyChange_t*)MSGpkt)->keys );
break;
// Received when a messages is received (OTA) for this endpoint
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB(MSGpkt);
break;
// Received whenever the device changes state in the network
case ZDO_STATE_CHANGE:
SampleApp_NwkState=(devStates_t)(MSGpkt->hdr.status);
if((SampleApp_NwkState== DEV_ZB_COORD)
||(SampleApp_NwkState== DEV_ROUTER)
||(SampleApp_NwkState== DEV_END_DEVICE))
{
// Start sending the periodic message in a regular interval.
osal_start_timerEx(SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
// Device is no longer in the network
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate((uint8*)MSGpkt);
// Next - if one is available
MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(SampleApp_TaskID);// Get the next message
}
/******************************************************
After processing the SYS_EVENT_MSG messages,
the processing function should return the unprocessed events:
*******************************************************/
return(events ^ SYS_EVENT_MSG);
// return unprocessed events}
// Send a message out - This event is generated by a timer
// (setup in SampleApp_Init()).
if( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();
// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx(SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT +(osal_rand()&0x00FF)));
// return unprocessed events
return(events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
// Discard unknown events
return0;
}
当然这里的任务处理函数可以看到两大类任务:
SYS_EVENT_MSG与
SAMPLEAPP_SEND_PERIODIC_MSG_EVT
我的理解:(1)
SYS_EVENT_MSG
(0x8000),是osal操作系统的系统等待轮询任务;一旦调用这个任务事件,
它必须得是以下子事件触发:AF_INCOMING_MSG_CMD :来自其它设备AF层发送过来的消息事件
KEY_CHANGE:用户按键事件
ZDO_STATE_CHANGE :网络状态变化事件
CMD_SERIAL_MSG:MT层串口发送过来的数据。(注意要加上MT.h头文件)
当然除了以上的Command IDs 外还有一些其它的。可以根据自己的应用需求而添加
(2)
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,定时器中断事件,要是需要定时或周期性的触发一些事件(比如周期发送消息)可以在此事件下面添加用户响应函数。
3. Message Flow(消息流)
AF_DataRequest();
![](https://images0.cnblogs.com/blog/665192/201411/242010302466946.png)