程序中事件如何被捕获呢?也就是tasksEvents这个数组里的元素什么时候被设定为非零数,来表示有事件需要处理的?
我将以SampleApp这个例程中按键事件的处理过程来说明。
刚看了一天的zigbee程序,任务的的处理机制还存在疑惑,经过查看前辈们的心得经验自己心中的谜团慢慢解开,下边就说一下自己的理解体会。
首先,按键被按下时会检测出来按键操作,我们需要找到事件处理函数即 Hal_ProcessEvent ,在HAL/Commen/Hal_devicers.c中很容易找到按键检测相关程序:
if (events & HAL_KEY_EVENT)
{
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
/* Check for keys */
HalKeyPoll();
/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
#endif // HAL_KEY
return events ^ HAL_KEY_EVENT;
}
程序中HalKeyPoll();是对按键状态的查询函数,
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
这个程序是对按键状态的检测,如果按键状态没有改变会延迟100毫秒并对Hal_TaskID这个ID所示的任务发送一个HAL_KEY_EVENT事件,这样可以理解为每100毫秒按键任务( 即Hal_ProcessEvent)就被执行一次按键状态的检测,HalKeyPoll这个函数就是检测按键key的实时状态值,在此函数中下列程序不难看出keys的状态值被保存
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
pHalKeyProcessFunction这个函数指针指向那个函数?
接下来我们看一下main函数中 InitBoard( OB_READY ); 这个函数,进入这个函数之后会看到
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);
然后我们找一下HalKeyConfig的定义,在HAL/Commen/Hal_devicers.c中HalDriverInit初始化函数中找到 HalKeyInit();进入
进入之后我们看到: pHalKeyProcessFunction = NULL;在初始化中pHalKeyProcessFunction并没有指向任何一个函数。
在HalKeyInit函数下边的一个函数我们看到是void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)函数,也就是我们刚要找的函数,在此函数中我们看到
pHalKeyProcessFunction = cback;
cback是HalKeyConfig传进来的参数,所以想知道pHalKeyProcessFunction所指向的函数必须找到其调用的地方,也就是我们刚刚在main函数中找到的InitBoard函数中 HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);
现在我们可以理解到 当发生按键任务事件时,Hal_ProcessEvent函数中HalKeyPoll()函数会获取按键变化的状态值,并把这状态值通过 (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);保存 ,而pHalKeyProcessFunction这个函数指针所指向的函数就是 HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);中的OnBoard_KeyCallback函数,所以Hal_ProcessEvent 任务处理函数中按键任务函数HalKeyPoll中(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);按键状态值发生变化后,对应的OnBoard_KeyCallback函数内部程序也会进行一系列的处理,
接下来看一下OnBoard_KeyCallback函数
void OnBoard_KeyCallback ( uint8 keys, uint8 state )
HalKeyPoll中按键状态值
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
我理解是参数一 一对应关系。
在OnBoard_KeyCallback函数中可以看到
OnBoard_SendKeys( keys, shift ) != ZSuccess这个程序,进入发送函数
uint8 OnBoard_SendKeys( uint8 keys, uint8 state )
{
keyChange_t *msgPtr;
if ( registeredKeysTaskID != NO_TASK_ID )
{
// Send the address to the task
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );
if ( msgPtr )
{
msgPtr->hdr.event = KEY_CHANGE;
msgPtr->state = state;
msgPtr->keys = keys;
osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );
}
return ( ZSuccess );
}
else
return ( ZFailure );
}
这样不难看出对于相应的任务状态值,其中osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );函数中registeredKeysTaskID这个与前边pHalKeyProcessFunction相同,怎么相同呢?
我们找到main函数进入osal_init_system->osalInitTasks->SampleApp_Init,在初始化中找到
RegisterForKeys( SampleApp_TaskID ); // 登记所有的按键事件
进入这个函数
uint8 RegisterForKeys( uint8 task_id )
{
// Allow only the first task
if ( registeredKeysTaskID == NO_TASK_ID )
{
registeredKeysTaskID = task_id;
return ( true );
}
else
return ( false );
}
我们可以知道registeredKeysTaskID 所指示的任务就是我们所需要响应按键的SampleApp这个任务
osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );那这个就是我们向SampleApp发送了一个附带按键信息的消息
进入这个函数uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr )
找到 osal_set_event( destination_task, SYS_EVENT_MSG );这个函数作用就是设置destination_task这个事件为SYS_EVENT_MSG ,而destination_task正是由osal_msg_send这个函数通过传参而来的,指的就是SampleApp这个任务。
进入函数
uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
if ( task_id < tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)
HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts
return ( SUCCESS );
}
else
{
return ( INVALID_TASK );
}
}
在函数中我们可以看到 tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)
到这里就可以和void osal_run_system( void )这个系统任务函数联系到一起,实现从任务事件的触发到系统任务的执行
(开始自己个人经验小结,有问题多多指教)