main函数先执行初始化工作,包括硬件、网络层、任务等的初始化。
一 系统初始化
系统初始化函数主要完成内存分配、消息队列头、定时器、电源管理、任务系统及内存栈等的初始化,具体如下代码所示:
//osal.c
1 uint8 osal_init_system( void ) 2 { 3 // Initialize the Memory Allocation System 4 osal_mem_init();/*初始化内存分配系统*/ 5 6 // Initialize the message queue 7 osal_qHead = NULL; /*初始化系统消息队列*/ 8 9 // Initialize the timers 10 osalTimerInit(); /*初始化定时器*/ 11 12 // Initialize the Power Management System 13 osal_pwrmgr_init(); /*初始化电源管理系统*/ 14 15 // Initialize the system tasks. 16 osalInitTasks();/*初始化系统任务*/ 17 18 // Setup efficient search for the first free block of heap. 19 osal_mem_kick(); 20 21 return ( SUCCESS ); 22 }
二 任务初始化
任务初始化,就是为系统的各个任务分配存储空间,初始化后,内存空间为全0(NULL),然后为各任务分配任务标识号taskID。即,这里重点是各任务的初始化,MAC层和NWK层的未开源看不到。
//OSAL_SampleApp.c
1 void osalInitTasks( void ) 2 { 3 uint8 taskID = 0; 4 5 tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//为当前OSAL中的各任务分配存储空间(实际上是一个任务数组),函数返回指向任务缓冲区的指针,因此tasksEvents指向该任务数组的首地址。 6 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); 7 //把开辟的内存全部设置为0;sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间 8 macTaskInit( taskID++ );//初始化各层任务 mac_taskID=0; 9 nwk_init( taskID++ ); 10 Hal_Init( taskID++ ); 11 #if defined( MT_TASK ) 12 MT_TaskInit( taskID++ ); 13 #endif 14 APS_Init( taskID++ ); 15 #if defined ( ZIGBEE_FRAGMENTATION ) 16 APSF_Init( taskID++ ); 17 #endif 18 ZDApp_Init( taskID++ ); 19 #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT ) 20 ZDNwkMgr_Init( taskID++ ); 21 #endif 22 SampleApp_Init( taskID );//SampleApp_taskID=6;用户创建的任务 23 }
系统主循环函数里tasksEvents[ idx]和tasksArr[ idx]的idx与这里taskID是一一对应关系。数组tasksEvents[]里面元素是各任务事件,不是指向任务事件的指针,数组tasksArr[ ]是这个指针数组,里面元素是指向各任务事件处理函数的指针,这两个指针数组里面各元素的顺序要一一对应,因为后面需要相应任务调用相应事件处理函数。如下代码所示,其中的xx_loop与上面的yy_init是一一对应的关系。
//OSAL_Tasks.h typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event ); //OSAL_SampleApp.c 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 }; const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
三 应用初始化
1 void SampleApp_Init( uint8 task_id ) 2 { 3 SampleApp_TaskID = task_id;//osal分配的任务ID,这里为6,随着用户添加任务的增多而改变 4 SampleApp_NwkState = DEV_INIT;//设备状态设定为ZDO层中定义的初始化状态(无连接) 5 SampleApp_TransID = 0;//消息发送ID(多消息时有顺序之分)
6 7 // Device hardware initialization can be added here or in main() (Zmain.c). 8 // If the hardware is application specific - add it here. 9 // If the hardware is other parts of the device add it in main(). 10 //以下是通过跳线判断是路由器还是协调器 11 #if defined ( BUILD_ALL_DEVICES ) 12 // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START 13 // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered 14 // together - if they are - we will start up a coordinator. Otherwise, 15 // the device will start as a router. 16 if ( readCoordinatorJumper() ) 17 zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR; 18 else 19 zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER; 20 #endif // BUILD_ALL_DEVICES 21 //以下是决断是通过外部按键触发还是系统启动过程中触发启动芯片 22 #if defined ( HOLD_AUTO_START ) 23 // HOLD_AUTO_START is a compile option that will surpress ZDApp 24 // from starting the device and wait for the application to 25 // start the device. 26 ZDOInitDevice(0); 27 #endif 28 //以下代码设置网络的通讯方式 29 // Setup for the periodic message's destination address 30 // Broadcast to everyone 31 SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; 32 SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; 33 SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF; 34 35 // Setup for the flash command's destination address - Group 1 36 SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; 37 SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; 38 SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; 39 40 // Fill out the endpoint description. 41 SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; 42 SampleApp_epDesc.task_id = &SampleApp_TaskID; 43 SampleApp_epDesc.simpleDesc 44 = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; 45 SampleApp_epDesc.latencyReq = noLatencyReqs; 46 47 // Register the endpoint description with the AF 48 afRegister( &SampleApp_epDesc ); 49 50 // Register for all key events - This app will handle all key events 51 RegisterForKeys( SampleApp_TaskID ); 52 53 // By default, all devices start out in Group 1 54 SampleApp_Group.ID = 0x0001; 55 osal_memcpy( SampleApp_Group.name, "Group 1", 7 ); 56 aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); 57 58 #if defined ( LCD_SUPPORTED ) 59 HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 ); 60 #endif 61 }
以上为OSAL初始化大体流程,OSAL以及各软硬部件初始化完成后,就进入了系统主循环函数osal_start_system(),下节将介绍此。
四 参考链接