ZStack版本:Z-Stack 3.0.2
下载和调试器:SmartRF04EB
IDE开发软件:IAR Embedded Workbench IDE - 8051 10.20.1
开发平台:基于TI-CC2530的任意厂家的
Z-Stack协议栈是TI对应zigbee协议的实现,目前最新的版本是 3.0.2。
Z-Stack协议栈里植入了OSAL实时操作系统,下面我们简单介绍一下这个操作系统:
名称:OSAL(Operating System Abastraction Layer)
作用:任务调度,资源分配和管理
要点:任务和事件
tasksCnt 任务个数
tasksEvents 任务事件表首地址的指针
tasksArr 数组,数组每个元素对应一个任务事件处理函数的指针
tasksEvents 和tasksArr是对应的,
OSAL只做了两件事情:首先进行系统的初始化,然后启动OSAL操作系统。最后就是任务轮询过程,系统将会不断查询每个任务是否有事件发生,如果有事件发生,就调用相应的事件处理函数,处理完成后,清除当前任务的事件标志,如果没有事件发生,则查询下一个任务。
1、main函数的分析
TI的Z-Stack协议是用C语言编写的,程序的入口点就是main()函数,而且整个Z-Stack都只有一个main()函数入口,所以程序的入口点也是main()函数,在Z-Stack 3.0.2协议栈中有四个main函数的定义,分别位于.Z-Stack 3.0.2\Projects\zstack\ZMain中的四个文件夹中,这四个文件分别对应了2种芯片和四种工程类型。针对CC2530来说,TI2530DB是单CC2530架构工程,TI2530ZNP是CC2530+MCU架构工程,在此我们只分析TICC2530DB的。 main()函数开始分析:
int main( void )
{
// Turn off interrupts
osal_int_disable( INTS_ALL );//关闭所有中断
// Initialization for board related stuff such as LEDs
HAL_BOARD_INIT();//板子硬件初始化,时钟,LED灯
// Make sure supply voltage is high enough to run
zmain_vdd_check();//电压检测,确保芯片可正常启动
// Initialize board I/O
InitBoard( OB_COLD );//板载I/O初始化
// Initialze HAL drivers
HalDriverInit();//硬件驱动初始化
// Initialize NV System
osal_nv_init( NULL );//FLASH存储器初始化
// Initialize the MAC
ZMacInit();//MAC层初始化
// Determine the extended address
zmain_ext_addr();//扩展地址确定
#if defined ZCL_KEY_ESTABLISH
// Initialize the Certicom certificate information.
zmain_cert_init();//认证初始化
#endif
// Initialize basic NV items
zgInit();//基本NV条目初始化
#ifndef NONWK
// Since the AF isn't a task, call it's initialization routine
afInit();//应用框架初始化
#endif
// Initialize the operating system
osal_init_system();//操作系统初始化
// Allow interrupts
osal_int_enable( INTS_ALL );//打开中断
// Final board initialization
InitBoard( OB_READY );//板子的最终初始化
// Display information about this device
zmain_dev_info();//设备信息的显示,需要LCD支持
/* Display the device info on the LCD */
#ifdef LCD_SUPPORTED
zmain_lcd_init();//如果定义LCD_SUPPORTED宏,则初始化LCD
#endif
#ifdef WDT_IN_PM1
/* If WDT is used, this is a good place to enable it. */
WatchDogEnable( WDTIMX );//看门狗使能
#endif
osal_start_system(); // No Return from here 启动操作系统,无返回
return 0; // Shouldn't get here.
} // main()
main函数主要在系统启动后,进行一些硬件、服务、操作系统等方面的初始化工作,最后启动操作系统。在main函数里的所有初始化函数中,有两个比较重要的函数是:osal_init_system();//初始化操作系统和
osal_start_system(); // No Return from here 启动操作系统。
2、osal_init_system()函数的分析
osal_init_system()在整个Z-Stack 3.0.2协议中,只有一处定义,上面说的四种工程类型中的main文件,只是对该函数进行调用即可。函数主要初始化了操作系统用到的资源,比如:内存,堆栈等,但我们重点关注的是操作系统任务初始化函数osalInitTasks();
uint8 osal_init_system( void )
{
#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
// Initialize the Memory Allocation System
osal_mem_init();//初始化内存
#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */
// Initialize the message queue
osal_qHead = NULL;//初始化消息队列
// Initialize the timers
osalTimerInit();//初始化定时器
// Initialize the Power Management System
osal_pwrmgr_init();//初始化电源管理系统
#ifdef USE_ICALL
/* Prepare memory space for service enrollment */
osal_prepare_svc_enroll();//准备用于服务注册的内存空间
#endif /* USE_ICALL */
// Initialize the system tasks.
osalInitTasks();//初始化系统任务,**需要重点分析**
#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
// Setup efficient search for the first free block of heap.
osal_mem_kick();
#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */
#ifdef USE_ICALL
// Initialize variables used to track timing and provide OSAL timer service
osal_last_timestamp = (uint_least32_t) ICall_getTicks();
osal_tickperiod = (uint_least32_t) ICall_getTickPeriod();
osal_max_msecs = (uint_least32_t) ICall_getMaxMSecs();
/* Reduce ceiling considering potential latency */
osal_max_msecs -= 2;
#endif /* USE_ICALL */
return ( SUCCESS );
}
3、osalInitTasks()任务初始化函数的分析
osalInitTasks()函数在Z-Stack 3.0.2协议栈中有多处定义,如下图所示:
除第一个操作系统OSAL.c文件的函数osal_init_system()函数是调用该函数外,其余文件中均有一个该文件的定义。其中不同文件代表了TI的不同类型的工程例程。而且每个文件还可用于不同芯片和架构。比如同一文件OSAL_GenericApp.C可用于TICC2530单芯片架构和单芯片+MCU架构,TICC2538单芯片架构和单芯片+MCU架构。我们在此,仅以OSAL_GenericApp.C文件进行分析。这是TI给出的一个通用的例程,我们先分析该文件中的
osalInitTasks()函数,再分析其它函数,代码如下:
/*********************************************************************
* @fn osalInitTasks
*
* @brief This function invokes the initialization function for each task.
*
* @param void
*
* @return none
*/
void osalInitTasks( void )
{
uint8 taskID = 0;//任务ID初始化,即任务的优先级
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//任务时间表内存分配
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//将全部内容初始化为0
macTaskInit( taskID++ );//taskID = 1 MAC层任务初始化
nwk_init( taskID++ );//taskID = 2 网络层任务初始化
#if !defined (DISABLE_GREENPOWER_BASIC_PROXY) && (ZG_BUILD_RTR_TYPE)
gp_Init( taskID++ );//taskID = 3 电源管理任务初始化
#endif
Hal_Init( taskID++ );//taskID = 4 硬件层任务初始化
#if defined( MT_TASK )
MT_TaskInit( taskID++ );//taskID = 5 串口监控任务初始化
#endif
APS_Init( taskID++ );//taskID = 6 APS层任务初始化
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_Init( taskID++ );//taskID = 7 APSF层任务初始化
#endif
ZDApp_Init( taskID++ );//taskID = 8 MAC层任务初始化
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_Init( taskID++ );//taskID = 9 任务初始化
#endif
// Added to include TouchLink functionality
#if defined ( INTER_PAN )
StubAPS_Init( taskID++ );//taskID = 10 任务初始化
#endif
// Added to include TouchLink initiator functionality
#if defined( BDB_TL_INITIATOR )
touchLinkInitiator_Init( taskID++ );//taskID = 11 任务初始化
#endif
// Added to include TouchLink target functionality
#if defined ( BDB_TL_TARGET )
touchLinkTarget_Init( taskID++ );//taskID = 12 任务初始化
#endif
zcl_Init( taskID++ );//taskID = 13 ZCL任务初始化
bdb_Init( taskID++ );//taskID = 14 bdb任务初始化
zclGenericApp_Init( taskID );//taskID = 15 本工程主任务初始化,重点关注
}