Z-stack ——osal
- osal 启动流程

osal流程图

协调器工作流程

终端器工作流程
- z-stack中事件和任务的事件处理函数是如何联系的??

zigbee协议栈中的三个重要的变量:
tasksCnt:任务的总个数
tasksEvents:指针变量,指向了事件表的首地址
tasksArr:数组(如下代码定义的),数组的每一项都是一个函数指针,指向了事件处理函数
const pTaskEventHandlerFn tasksArr[]={macEventLoop,nwk_event_loop,Hal_ProcessEvent,#if defined( MT_TASK )MT_ProcessEvent,#endifAPS_event_loop,#if defined ( ZIGBEE_FRAGMENTATION )APSF_ProcessEvent,#endifZDApp_event_loop,#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_event_loop,#endifSampleApp_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;elsezgDeviceLogicalType = 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 everyoneSampleApp_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 1SampleApp_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 AFafRegister(&SampleApp_epDesc);// Register for all key events - This app will handle all key eventsRegisterForKeys(SampleApp_TaskID);// By default, all devices start out in Group 1SampleApp_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 parameterif( events & SYS_EVENT_MSG ){MSGpkt=(afIncomingMSGPacket_t*)osal_msg_receive(SampleApp_TaskID);//从消息队列上接收消息while(MSGpkt){switch(MSGpkt->hdr.event ){// Received when a key is pressedcase KEY_CHANGE:SampleApp_HandleKeys(((keyChange_t*)MSGpkt)->state,((keyChange_t*)MSGpkt)->keys );break;// Received when a messages is received (OTA) for this endpointcase AF_INCOMING_MSG_CMD:SampleApp_MessageMSGCB(MSGpkt);break;// Received whenever the device changes state in the networkcase 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 memoryosal_msg_deallocate((uint8*)MSGpkt);// Next - if one is availableMSGpkt=(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 messageSampleApp_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 eventsreturn(events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);}// Discard unknown eventsreturn0;}
当然这里的任务处理函数可以看到两大类任务: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();
浙公网安备 33010602011771号