零、注意:
一方面switch ( MSGpkt->hdr.event )
另一方面:SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
afIncomingMSGPacket_t *MSGpkt; 转为(keyChange_t *)MSGpkt,而且还要用到switch ( MSGpkt->hdr.event ),那么他们的前面的变量必须相同,不同的变量在后面。
typedef struct
{
osal_event_hdr_t hdr;
uint16 groupId;
uint16 clusterId;
afAddrType_t srcAddr;
byte endPoint;
byte wasBroadcast;
byte LinkQuality;
byte SecurityUse;
uint32 timestamp;
afMSGCommandFormat_t cmd;
} afIncomingMSGPacket_t;
typedef struct
{
osal_event_hdr_t hdr;
byte state; // shift
byte keys; // keys
} keyChange_t;
一、osal_start_system()
在系统初始化各项工作做完后,调用osal_start_system()一直循环,不返回。
#if !defined ( ZBIT ) //一般是define ZBIT的
Hal_ProcessPoll() ; //将Timer1、Timer3、Timer4进行初始化,如果允许定义了HAL_UART,则初始化UART,一般是没有define HAL_UART的。
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt);
//每一类型的task都对应一个tasksEvent数组中的一个idx。idx越小,优先级越高,因此是按高优先级优先执行
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 ); //处理函数,每个idx对应不同的处理函数名。返回的值
如果成功则为0,如果不成功则有其他的值,后面会 位或 来得到执行的状态(可以是继续执行
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
二、SampleApp_ProcessEvent
typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
ZDApp_event_loop,
SampleApp_ProcessEvent
};
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events );
函数SampleApp_ProcessEvent首先判断事件类型,
1)如果事件为SAMPLEAPP_SEND_PERIODIC_MSG_EVT,则不需要对接收包进行处理,直接发送周期信息,并且将该taskId和 周期事件 注册到 定时时间链表(timer*)中。
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();
SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );
// 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)) ); //osal_start_timerEx最后一个参数 在timeout变量基础上增加了0~127ms随机
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);//将周期发送的位标志清空
}
a) osal_start_timerEx( byte taskID, UINT16 event_id, UINT16 timeout_value )函数调用
osalAddTimer( byte task_id, UINT16 event_flag, UINT16 timeout )将当前的任务 和 事件添加到 定时器记录链表中。osalAddTimer在开始时先调用osalFindTimer查询当前存在定时器。
osalFindTimer很有意思(其中timerhead是全局指向Timer链表的头指针):
osalTimerRec_t *osalFindTimer( byte task_id, uint16 event_flag )
{
osalTimerRec_t *srchTimer;
// Head of the timer list
srchTimer = timerHead;
// Stop when found or at the end
while ( srchTimer )
{
if ( srchTimer->event_flag == event_flag &&
srchTimer->task_id == task_id )
break;
// Not this one, check another
srchTimer = srchTimer->next;
}
return ( srchTimer );
}
在开始时如果链表为空,则返回空,如果该定时器列表已经存在而且不包括当前需要插入的任务和时间号,同样返回空; 如果该链表中已经存在当前的任务和事件号则返回当期非空的指针。
所以在外层函数osalAddTimer中可以判断返回值是否为空 来决定是不是要将当前的任务和事件号插入。如果为空,则需要重新分配一块区域给Timer。
if ( newTimer )
{
// Timer is found - update it.
newTimer->timeout = timeout;
return ( newTimer );
}
else
{
// New Timer
newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) );
if ( newTimer )
{
// Fill in new timer
newTimer->task_id = task_id;
newTimer->event_flag = event_flag;
newTimer->timeout = timeout;
newTimer->next = (void *)NULL;
// Does the timer list already exist
if ( timerHead == NULL )
{
// Start task list
timerHead = newTimer;
}
else
{
// Add it to the end of the timer list
srchTimer = timerHead;
// Stop at the last record
while ( srchTimer->next )
srchTimer = srchTimer->next;
// Add to the list
srchTimer->next = newTimer;
}
return ( newTimer );
}
else
return ( (osalTimerRec_t *)NULL );
}
2)如果事件类型为SYS_EVENT_MSG, 函数调用osal_msg_receive(byte task_id)在 临界区 中读取当前接收的afIncomingMSGPacket_t 类型的数据。
a)获取MSGpkt
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
byte *osal_msg_receive( byte task_id )
typedef void * osal_msg_q_t;
osal_msg_q_t osal_qHead; //(因此osal_qHead是全局的 void* 指针,指向的类型不定,这也决定osal_msg_receive(SampleApp_TaskID );返回的是byte *类型。
typedef struct
{
void *next;
uint16 len;
byte dest_id;
} osal_msg_hdr_t;
函数需要判断if ( (listHdr - 1)->dest_id == task_id ),也就是说这个消息链表不是按taskid分开得,不是按id排序的。
while ( listHdr != NULL )
{
if ( (listHdr - 1)->dest_id == task_id )
{
break;
}
prevHdr = listHdr;
listHdr = OSAL_MSG_NEXT( listHdr );
}
所得到的是当前task_id的 消息链表(不仅仅是一个消息)
osal_msg_hdr_t *listHdr;
return ( (byte*) listHdr );
b)处理MSGpkt
(1)KEY_CHANGE
(2)AF_INCOMING_MSG_CMD
(3)ZDO_STATE_CHANGE,终端的state改变了,发送到协调器,协调器对其进行处理。