zigbee任务的处理流程
来源:互联网 发布:5vb阻燃级别 编辑:程序博客网 时间:2024/04/28 10:46
1、 添加任务
在协议栈中的OSAL.c文件中,byte osal_init_system( void )函数的功能是初始化OS、添加任务到OS任务表中。在这个函数中通过调用osalAddTasks()函数来定制项目所需要应用的任务,该函数属于应用层和OS之间的接口函数,一般项目的建立需要根据系统的需要自己编写改函数,并将函数放到应用层。osalAddTasks()函数是通过osalTaskAdd()函数完成任务添加。
值得注意的是在一个空的协议栈里osalAddTasks()只是在OSAL_Custom.h中申明,并未写出具体操作,需要我们在自己在接口处编写,osalTaskAdd()函数也是自己加进去的
osalTaskAdd()已经不支持,现在用下面的方法添加任务
在协议栈ZStack-CC2430-1.4.3中是这样添加任务的:
1)任务初始化函数的添加
main ()
--->byte osal_init_system( void ) 【OSAL.c】
--->osalInitTasks()【OSAL_SampleApp.c】 //初始化系统任务
---> void SampleApp_Init( uint8 task_id )【SampleApp.c】//应用初始化
2)任务处理函数的流程
首先在任务函数列表中添加处理函数
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
ZDApp_event_loop,
SampleApp_ProcessEvent
};
该列表中处理函数的出现的顺序需要和osalInitTasks()函数中初始化的顺序一致
oid osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID++ );
nwk_init( taskID++ );
Hal_Init( taskID++ );
#if defined( MT_TASK )
MT_TaskInit( taskID++ );
#endif
APS_Init( taskID++ );
ZDApp_Init( taskID++ );
SampleApp_Init( taskID ); //注意顺序要和pTaskEventHandlerFn中处理函数一致
}
2、 任务初始化--- void SampleApp_Init( uint8 task_id )【SampleApp.c】
命名规则:应用名_init()
初始化内容:
初始化Application Objects对应的变量
相应Application Objects的实例化—afRegister()
注册应用OSAL或HAL系统服务—RegisterForKeys()
/*********************************************************************
* @fn SampleApp_Init
*
* @brief Initialization function for the Generic App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by OSAL. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
// 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 ( SOFT_START )
// The "Demo" target is setup to have SOFT_START and HOLD_AUTO_START
// SOFT_START is a compile option that allows the device to start
// as a coordinator if one isn't found.
// 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 // SOFT_START
#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 ); //注册按键事件后,按键回调函数将会把OSAl系统事件KEY_CHANGE发送到注册的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、 任务处理---uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )【SampleApp.c】
1)当SampleApp_TaskID对应的OSAL事件发生时,在OSAL的主循环函数会调用该处理函数;
2)SYS_EVENT_MSG是全局系统消息,该消息包含以下消息:
--AF_DATA_CONFIRM_CMD
--AF_INCOMING_MSG_CMD
--KEY_CHANGE
--ZDO_STATE_CHANGE
3)如果一个OSAL任务已经注册为按键按下通知,则任何的按键事件将会以KEY_CHANGE系统事件消息的形式接收。有两种可能的程序流程会使一个任务接收到此KEY_CHANGE
物理层按键的程序流程如下:
--HAL检测按键状态(通过H/W中断或H/W循环检测);
--HAL OSAL任务检测到一个按键状态变化,并调用OSAL按键变化回调函数;
--OSAL按键变化回调函数发送OSAL系统事件消息KEY_CHANGE到通过RegisterForKeys()注册的TaskID
4)TransID 其作用是识别消息,可为每个不同的Endpoint或每个clusterID对应的事件设置一TransID以对其进行区别。
/*********************************************************************
* @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;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); //从OS的消息队列中接收一个消息
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;
zigbee任务的处理流程(二)
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is available
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();
// 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;
}
5)在该实例程序中,按键处理程序SampleApp_HandleKeys对按键进行处理:
(1)按键1—向group1的设备发送闪烁消息SampleApp_SendFlashMessage()
该函数中的SampleApp_Flash_DstAddr为发送的目的地址,该参数在SampleApp_Init()中初始化为组1:
// 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;
所以设备在初始化时初始化为组1,组初始化方法为:
aps_Group_t SampleApp_Group;
….
SampleApp_Group.ID = 0x0001;
Osal_memcpy(SampleApp_Group.name,”Group 1”,7);
aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group);
aps_Group_t结构体为:
typedef struct
{
Uint16 ID;
Uint8 name[APS_GROUP_NAME_LEN];
}aps_Group_t;
按键1的处理函数为:
void SampleApp_SendFlashMessage( uint16 flashTime )
{
uint8 buffer[3];
buffer[0] = (uint8)(SampleAppFlashCounter++); //发送闪烁消息的次数
buffer[1] = LO_UINT16( flashTime ); //闪烁频率的计数
buffer[2] = HI_UINT16( flashTime );
if ( AF_DataRequest( &SampleApp_Flash_DstAddr, //目的的组地址,group1
&SampleApp_epDesc, //源EndPoint description
SAMPLEAPP_FLASH_CLUSTERID, //cluster ID
3, //要发送数据的长度
buffer, //发送数据的指针
&SampleApp_TransID, //事物需要指针,若果消息缓存发送,这个函数将会增加此数
AF_DISCV_ROUTE, //发送选项
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}
注:AF_DataRequest生命如下
afStatus_t AF_DataRequest( afAddrType_t *dstAddr,
endPointDesc_t *srcEP,
uint16 cID,
uint16 len,
uint8 *buf,
uint8 *transID,
uint8 options,
uint8 radius )
该函数中参数option为以下值:
AF_ACK_REQUEST 0x10---请求,应用层调用,要求APS应答,这是应用层的应答,只在直接发送(单播)时使用
AF_DISCV_ROUNTE 0x20 ---路由发现,总是包含此项
AF_SKIP_RONTING 0x80---使设备跳过路由而直接发送消息,终点设备将不向其父亲发送消息
(2)按键2—按一次会使设备脱离组1,再按一次会使设备加入组1
aps_Group_t *grp;
grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
if ( grp )
{
// Remove from the group
aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
}
else
{
// Add to the flash group
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
}
i. 接收到的消息处理
若收到AF_INCOMING_MSG_CMD,则调用函数SampleApp_MessageMSGCB()【SampleApp.c】对消息进行处理。
ii. osal_start_timerEx( )
为指定的task启动定时器,当定时器到时后,指定的event位将会置位
byte osal_start_timerEx( byte taskID, UINT16 event_id, UINT16
timeout_value);
taskID—定时器到时时获取event的task ID,即event通知给task ID
event_id ---用户定义的event bit,当定时器到时后,会向task id通知event
timeout_value---时间(微秒)
- zigbee任务的处理流程
- zigbee任务的处理流程
- zigbee消息的处理流程
- ZIGBEE: 任务处理分析
- zigbee任务的添加
- ZigBee 中 z-Stack协议中的任务、事件、消息处理流程
- ZIGBEE--OSAL处理来自AF的数据包流程
- Zigbee的组网流程
- zigbee协议栈之按键处理流程
- Spark任务处理流程
- Spark任务处理流程
- 任务处理表tasksEvents是怎么被改动的及zigbee协议栈分析
- ZigBee网络的建立 & ZigBee系统初始化流程
- ZigBee串口的运行流程以及修改
- zigbee 任务调度机制
- zigbee 任务调度系统
- ZigBee添加用户任务
- Zigbee绑定流程
- 字典
- MyEclipse的 applicationContext.xml上有红叉
- 关于windows下redis频繁get 和set相同值遇到的问题
- 细说嵌入式领域的那些专业厂商认证
- MySQL Migration Toolkit工具sql转mysql乱码问题
- zigbee任务的处理流程
- 摄像头的自动对焦
- windows下搭建hadoop+eclipse开发环境
- 如何判断自己是否具有成为一名优秀程序员的潜质
- PHP 从 URL 中提取域名 函数
- 启动Apache时提示错误“Cannot load php5apache2_2.dll into server”
- Android与linux的区别与联系
- win7 64位机器下,注册控件的问题。
- 取缔余额宝 是高估了余额宝还是低估了银行