上一节分析完了系统初始化,现在来看看用户定义任务的执行流程。
上节说到入口在) SampleApp_ProcessEvent() 用户定义的事件处理函数
我们来看源码SimpleApp.c中函数的定义:
/*********************************************************************
* @fn SampleApp_ProcessEvent
*
* @brief Generic Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The OSAL assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return none
*/
//用户应用任务的事件处理函数
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG ) //接收系统消息再进行判断
{
//接收属于本应用任务SampleApp的消息,以SampleApp_TaskID标记
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://接收数据事件,调用函数AF_DataRequest()接收数据
SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理
break;
// Received whenever the device changes state in the network
case ZDO_STATE_CHANGE:
//只要网络状态发生改变,就通过ZDO_STATE_CHANGE事件通知所有的任务。
//同时完成对协调器,路由器,终端的设置
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
//if ( (SampleApp_NwkState == DEV_ZB_COORD)//实验中协调器只接收数据所以取消发送事件
if ( (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 指针指向下一个放在缓冲区的待处理的事件,
//返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
}
// return unprocessed events 返回未处理的事件
return (events ^ SYS_EVENT_MSG);
}
// 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()处理完当前的周期性事件,然后启动定时器
//开启下一个周期性事情,这样一种循环下去,也即是上面说的周期性事件了,
//可以做为传感器定时采集、上传任务
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
return 0;
}
1)先看函数定义
taskid比较好理解,是操作系统分配的任务ID
event包括定时器,消息或其他用户自定义事件
2)看看消息数据结构的定义(AF.H):
typedef struct
{
osal_event_hdr_t hdr; /* OSAL Message header */
uint16 groupId; /* Message's group ID - 0 if not set */
uint16 clusterId; /* Message's cluster ID */
afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
it's an InterPAN message */
uint16 macDestAddr; /* MAC header destination short address */
uint8 endPoint; /* destination endpoint */
uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */
uint8 LinkQuality; /* The link quality of the received data frame */
uint8 correlation; /* The raw correlation value of the received data frame */
int8 rssi; /* The received RF power in units dBm */
uint8 SecurityUse; /* deprecated */
uint32 timestamp; /* receipt timestamp from MAC */
afMSGCommandFormat_t cmd; /* Application Data */
} afIncomingMSGPacket_t;
能设断点跟踪下? 解析例程收到的数据包
3)case开始处理不同分支:
大分支两个,要么处理系统消息,要么处理周期性任务
if ( events & SYS_EVENT_MSG )
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
两个事件都不符合,则返回0
查看这两个宏定义:
comdef.h中
/*********************************************************************
* Global System Events
*/
#define SYS_EVENT_MSG 0x8000 // A message is waiting event
SampleApp.h中
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001
4)看看系统消息处理的分支:
先确认属于本任务ID的消息
程序里跟踪系统消息包MSGpkt的内容:
看看hdr结构体的定义:
typedef struct
{
uint8 event;
uint8 status;
} osal_event_hdr_t;
有多少种消息定义呢? ,跟踪到ZComDef.h
/*********************************************************************
* Global System Messages
*/
#define SPI_INCOMING_ZTOOL_PORT 0x21 // Raw data from ZTool Port (not implemented)
#define SPI_INCOMING_ZAPP_DATA 0x22 // Raw data from the ZAPP port (see serialApp.c)
#define MT_SYS_APP_MSG 0x23 // Raw data from an MT Sys message
#define MT_SYS_APP_RSP_MSG 0x24 // Raw data output for an MT Sys message
#define AF_DATA_CONFIRM_CMD 0xFD // Data confirmation
#define AF_INCOMING_MSG_CMD 0x1A // Incoming MSG type message
#define AF_INCOMING_KVP_CMD 0x1B // Incoming KVP type message
#define AF_INCOMING_GRP_KVP_CMD 0x1C // Incoming Group KVP type message
//#define KEY_CHANGE 0xC0 // Key Events
#define ZDO_NEW_DSTADDR 0xD0 // ZDO has received a new DstAddr for this app
#define ZDO_STATE_CHANGE 0xD1 // ZDO has changed the device's network state
#define ZDO_MATCH_DESC_RSP_SENT 0xD2 // ZDO match descriptor response was sent
#define ZDO_CB_MSG 0xD3 // ZDO incoming message callback
#define ZDO_NETWORK_REPORT 0xD4 // ZDO received a Network Report message
#define ZDO_NETWORK_UPDATE 0xD5 // ZDO received a Network Update message
#define NM_CHANNEL_INTERFERE 0x31 // NwkMgr received a Channel Interference message
#define NM_ED_SCAN_CONFIRM 0x32 // NwkMgr received an ED Scan Confirm message
#define SAPS_CHANNEL_CHANGE 0x33 // Stub APS has changed the device's channel
#define ZCL_INCOMING_MSG 0x34 // Incoming ZCL foundation message
#define ZCL_KEY_ESTABLISH_IND 0x35 // ZCL Key Establishment Completion Indication
// OSAL System Message IDs/Events Reserved for applications (user applications)
// 0xE0 ?0xFC
如果要增加系统消息类型,那应该在这里了