首页 > 代码库 > Z-stack ——osal
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,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
SampleApp_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(任务初始化)
void SampleApp_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;
else
zgDeviceLogicalType = 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 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 );
// 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-38:初始化本地变量与应用程序对象等;
代码41-51:将应用程序对象注册到AF层(afRegister( &SampleApp_epDesc ));登记注册到OSAL与HAL系统服务中( RegisterForKeys( SampleApp_TaskID );)。只有注册后才可以使用OSAL提供的系统服务。
2. Task Event Handler(任务处理)
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
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:
SampleApp_MessageMSGCB( MSGpkt );
break;
// Received whenever the device changes state in the network
case 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 memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is available
MSGpkt = (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 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;
}
当然这里的任务处理函数可以看到两大类任务: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();
来自为知笔记(Wiz)
Z-stack ——osal
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。