如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.
分类: LINUX
2013-04-19 17:21:20
2、系统初始化流程
2.1osal_init_system()——系统初始化函数
Uint8 osal_init_system( void )
{
// Initialize the Memory Allocation System
/*初始化内存分配系统*/
osal_mem_init();
// Initialize the message queue
/*初始化系统消息队列*/
osal_qHead = NULL;
#if defined( OSAL_TOTAL_MEM )
osal_msg_cnt = 0;
#endif
// Initialize the timers
/*初始化定时器*/
osalTimerInit();
// Initialize the Power Management System
/*初始化电源管理系统*/
osal_pwrmgr_init();
// Initialize the system tasks.
/*初始化系统任务*/
osalInitTasks(); //初始化系统任务
// Setup efficient search for the first free block of heap.
osal_mem_kick();
return ( ZSUCCESS );
}
说明:这里重点是初始化系统任务函数:osalInitTasks(); 下面进入系统任务的初始化:
//----------------------------------------------------------------------------------------------------
2.2 osalInitTasks(); ——任务初始化函数
void osalInitTasks( void )
{
uint8 taskID = 0;
//osal_mem_alloc()
为当前OSAL中的各任务分配存储空间(实际上是一个任务数组),函数返回指向任务缓冲区的指针,因此tasksEvents指向该任务数组的首地址。注意tasksEvents[]和后面谈到的tasksArr[]里的顺序是一一对应的, tasksArr[ ]中的第i个事件处理函数对应于tasksEvents[]中的第i个任务的事件。
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
//osal_memset()
把开辟的内存全部设置为0;sizeof( uint16 )是4个字节,即一个任务的长度(同样是uint16定义),乘以任务数量tasksCnt,即全部内存空间
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); //OSAL.c中定义
macTaskInit( taskID++ ); //初始化各层任务 mac_taskID=0;
nwk_init( taskID++ ); //nwk_taskID=1;
Hal_Init( taskID++ ); //Hal_taskID=2;
#if defined( MT_TASK )
MT_TaskInit( taskID++ ); //MT_taskID=3;(if defined)
#endif
APS_Init( taskID++ ); //APS_taskID=4;
ZDApp_Init( taskID++ ); //ZDAPP_taskID=5;
SampleApp_Init( taskID ); //SampleApp_taskID=6;用户创建的任务
}
/*****************************************************************************************************/
任务初始化,就是为系统的各个任务分配存储空间,当然,这个空间初始化时为全0(NULL),然后为各任务分配taskID;
这里的顺序要注意.系统主循环函数里tasksEvents[ idx]和tasksArr[ idx]的idx与这里taskID是一一对应关系。
数组tasksEvents[ ]里面元素是各任务事件,不是指向任务事件的指针,后面文章具体分析。
数组tasksArr[ ]是这个指针数组,里面元素是指向各任务事件处理函数的指针。
这两个指针数组里面各元素的顺序要一一对应,因为后面需要相应任务调用相应事件处理函数.
/*****************************************************************************************************/
说明:那么这里重点是各任务的初始化,MAC层和NWK层的未开源看不到,先记录下用户自己添加的任务初始化函 数SampleApp_Init( taskID );
//----------------------------------------------------------------------------------------------------
2.3 SampleApp_Init( taskID ); ——用户应用任务初始化函数
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
//osal分配的任务ID,这里为6,随着用户添加任务的增多而改变
SampleApp_NwkState = DEV_INIT;
//设备状态设定为ZDO层中定义的初始化状态(无连接)
初始化应用设备的网络类型,设备类型的改变都要产生一个事件—ZDO_STATE_CHANGE,从字面理解为ZDO状态发生了改变。所以在设备初始化的时候一定要把它初始化为什么状态都没有。那么它就要去检测整个环境,看是否能重新建立或者加入存在的网络。但是有一种情况例外,就是当NV_RESTORE被设置的候(NV_RESTORE是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了.这里需要设置NV_RESTORE宏定义。
SampleApp_TransID = 0; //消息发送ID(多消息时有顺序之分)
#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.
该段的意思是,如果设置了HOLD_AUTO_START宏定义,将会在启动芯片的时候会暂停启动流程,只有外部触发以后才会启动芯片。其实就是需要一个按钮触发它的启动流程。
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;
//指定端点号EP20
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
//指定目的网络地址为广播地址
//闪烁消息:发送到组
// Setup for the flash command's destination address - Group1
闪烁消息事件
/*设置 endpoint description.*/
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
//(组寻址)
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
//EP20
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
//组号0x0001
// Fill out the endpoint description.
/*定义本设备用来通信的APS层端点描述符*/
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
//SampleApp EP描述符的EP号:20
SampleApp_epDesc.task_id = &SampleApp_TaskID;
//SampleApp EP描述符的任务ID:6
SampleApp_epDesc.simpleDesc= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; //SampleApp EP简单描述符
SampleApp_epDesc.latencyReq = noLatencyReqs;
//延时策略
// Register the endpoint description with the AF
/*向AF层登记EP描述符*/
/*登记endpoint description 到AF,要对该应用进行初始化并在AF进行登记,告诉应用层有这么一个EP已经开通可以使用,那么下层要是有关于该应用的信息或者应用要对下层做哪些操作,就自动得到下层的配合。*/
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 );
//把该组登记添加到APS中
/*如果支持LCD,显示一串字符*/
#if defined ( LCD_SUPPORTED )
//HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
Print8(HAL_LCD_LINE_2,20,"SampleApp",1);
#endif
}
在SampleAPP例子中,应用层提供了节点间两种逻辑关系:一种是周期性消息发送,另一种是Flash消息发送。
我个人认为就是两个簇,比如节点1的EP20与节点2的EP20通信,(可以单播,广播,间接,组传递),这两种逻辑关系属于两节点的EP20简单描述符下簇列表元素. 且可以看到SampleApp_SendPeriodicMessage( void )与SampleApp_SendFlashMessage( )下的clusterID项分别为SAMPLEAPP_PERIODIC_CLUSTERID和SAMPLEAPP_FLASH_CLUSTERID。用户应用任务初始化大致是:设置本应用发送数据的方式和目的地址寻址模式,登记注册本应用所用到的端点,以及配置相关发送模式所需的参数.
以上为OSAL初始化大体流程,OSAL以及各软硬部件初始化完成后,就进入了系统主循环函数osal_start_system();
参考文章为 http://wjf88223.blog.163.com。