ZIGBEE-Z-stack协议栈
Z-stack--一个小操作系统。用户通过 API 函数就可以轻易用 ZigBee。
协议栈主函数 ----Zmain.C
/****************************************************************
* @fn main
* @brief First function called after startup.
* @return don’t care
*/
int main( void )
{
// Turn off interrupts
osal_int_disable( INTS_ALL ); //关闭所有中断
// Initialization for board related stuff such as LEDs
HAL_BOARD_INIT(); //初始化系统时钟
// Make sure supply voltage is high enough to run
zmain_vdd_check(); //检查芯片电压是否正常
// Initialize board I/O
InitBoard( OB_COLD ); //初始化 I/O ,LED 、Timer 等
// Initialze HAL drivers
HalDriverInit(); //初始化芯片各硬件模块
// Initialize NV System
osal_nv_init( NULL ); // 初始化 Flash 存储器
// Initialize the MAC
ZmacInit(); //初始化 MAC 层
// Determine the extended address
zmain_ext_addr(); //确定 IEEE 64 位地址
// Initialize basic NV items
zgInit(); // 初始化非易失变量
#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(); //显示设备信息
/* Display the device info on the LCD */
#ifdef LCD_SUPPORTED
zmain_lcd_init();
#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.
}
重点了解 2 个函数:
1. 初始化操作系统 :osal_init_system(); <系统初始化函数>
有 6 个初始化函数,只需关心 osalInitTasks();<;任务初始化函数>
void osalInitTasks( void )
{
uint8 taskID = 0;
// 分配内存,返回指向缓冲区的指针
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
// 设置所分配的内存空间单元值为 0
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
// 任务优先级由高向低依次排列,高优先级对应 taskID 的值反而小
macTaskInit(taskID ++ ); //macTaskInit(0) ,用户不需考虑
nwk_init(taskID ++ ); //nwk_init(1),用户不需考虑
Hal_Init(taskID ++ ); //Hal_Init(2) ,用户需考虑
#if defined( MT_TASK )
MT_TaskInit(taskID ++ );
#endif
APS_Init(taskID ++ ); //APS_Init(3) ,用户不需考虑
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_Init(taskID ++ );
#endif
ZDApp_Init(taskID ++ ); //ZDApp_Init(4) ,用户需考虑
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_Init(taskID ++ );
#endif
SampleApp_Init(taskID ); // SampleApp_Init _Init(5) ,用户需考虑 ,重要函数
}
函数对 taskID 个东西进行初始化,每初始化一个,taskID++。
2. 运行操作系统 :osal_start_system();
这个是任务系统轮询的主要函数。他会查找发生的事件然后调用相应的事件执行函数。如果没有事件登记要发生,那么就进入睡眠模式。这个函数是永远不会返回的
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; // 得到待处理的最高优先级任务索引号 idx
}
} while (++idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // 进入临界区,保护
events = tasksEvents[idx]; /*提取需要处理的任务中的事件 taskID 一一对应。这就是初始化与调用的关系。taskID 把任务联系起来了。 */
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
}
}