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,(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;