ZigBee协议栈任务处理分析笔记

2019-01-19 18:59

ZigBee协议栈任务处理分析笔记

----(转载请注明出处 774910349@qq.com)Everhuai写于 2011-11-17

弄了这么久ZigBee协议栈,今天终于有一点头绪了,基本上知道了整个系统任务怎么被添加,又是怎么被切换的一个过程。下面就简单讲一讲这部分内容。

首先看的当然是main()函数,不过这个函数不是今天的重点,里面有我添加的注释,先就一笔带过吧。

int main( void ) {

// Turn off interrupts

osal_int_disable( INTS_ALL );//关闭全局中断EA=0,初始化过程不响应任何中断

// 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 stack memory zmain_ram_init();//初始化堆内存

// Initialize board I/O /初始化板子用到的IO口 InitBoard( OB_COLD );

// Initialze HAL drivers HalDriverInit();//初始化外设

// Initialize NV System //系统初始化 osal_nv_init( NULL );

// Initialize basic NV items//任务初始化 zgInit();

// Initialize the MAC ZMacInit();

// Determine the extended address //确定长地址 zmain_ext_addr(); #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 ); //sd rest // 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//正常情况下不返回

// Shouldn't get here return ( 0 ); } // main()

//使用看门狗

其中含有osal的都是与操作系统相关的。这里主要提一下这些函数:

// Initialze HAL drivers HalDriverInit();//初始化外设

片内外设与片外外设基本上在这个函数中初始化,像Timer、DMA、LCD等。该函数调用后设备即可使用。

// Initialize basic NV items zgInit();

这个函数通过调用

// Initialize the items table zgInitItems( setDefault );

初始化了zgItemTable[]//ZGlobal Item Table

我反正没搞懂这个数组干嘛用的,至少跟我们今天讨论的任务没有关系。我们讨论的任务在

// Initialize the operating system osal_init_system();

函数中调用osalInitTasks()进行初始化,在该函数中为每一个任务分配了一个ID号,这个ID号在任务切换的时候将用到。该函数中的初始化函数的顺序与函数指针数组

const pTaskEventHandlerFn tasksArr[] 中对应的任务的顺序是一致的,这一点不难理解,就是为了保证任务与ID号的对应。

该函数中还有这么两天语句值得注意:

tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);//申请空间,用于存放任务 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

//用0初始化申请到的空间

tasksEvents是一个指针,C语言好的不用看它的定义都看得出来。任务切换的时候就是通过tasksEvents来查找需要处理

的任务。tasksEvents指向的对象保存的是对应任务的掩码。

最后通过调用函数osal_start_system(); /* No Return from here*/启动操作系统,该函数正常情况下是不返回的。 #if !defined ( ZBIT ) && !defined ( UBIT ) for(;;) // Forever Loop #endif

然后所有的任务都在这个for循环中被处理:

{

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; }

} while (++idx < tasksCnt);//tasksCnt为总的任务数

if (idx < tasksCnt)//任务数检查 {

uint16 events; halIntState_t intState;

HAL_ENTER_CRITICAL_SECTION(intState);//保存中断状态 events = tasksEvents[idx];//取出任务后立即清除 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? {

//当任务ID号出错时进入睡眠

osal_pwrmgr_powerconserve(); // Put the processor/system into sleep } #endif

}

当有任务需要处理时便调用函数osal_set_event()添加任务:

/********************************************************************* * @fn osal_set_event * * @brief *

* This function is called to set the event flags for a task. The * event passed in is OR'd into the task's event variable. **设置事件标志,这些事件保存到变量task * @param uint8 task_id - receiving tasks ID * @param uint8 event_flag - what event to set *

* @return SUCCESS, INVALID_TASK */

uint8 osal_set_event( uint8 task_id, uint16 event_flag ) {

if ( task_id < tasksCnt )//正确的ID {

halIntState_t intState;

HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts

tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)/添加需要处理的事件的掩码 HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts } else

return ( INVALID_TASK );

return ( SUCCESS ); }

再看函数osal_start_system()对于tasksEvents就比较清楚了。

在所有调用osal_set_event()的函数中比较值得关注的是void osalTimerUpdate( uint16 updateTime )

先来看看函数体:

/********************************************************************* * @fn osalTimerUpdate *

* @brief Update the timer structures for a timer tick. *

* @param none *

* @return none **更新定时器任务

*********************************************************************/ void osalTimerUpdate( uint16 updateTime ) {

halIntState_t intState; osalTimerRec_t *srchTimer; osalTimerRec_t *prevTimer;

HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts./保存中断状态 // Update the system time/更新系统时间 osal_systemClock += updateTime;

HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts./恢复中断状态

// Look for open timer slot if ( timerHead != NULL ) {

// Add it to the end of the timer list/添加到定时器列表 srchTimer = timerHead; prevTimer = (void *)NULL;

// Look for open timer slot/遍历链表 while ( srchTimer ) {

osalTimerRec_t *freeTimer = NULL;

HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.

if (srchTimer->timeout <= updateTime)//超时检查 {

srchTimer->timeout = 0; } else {

srchTimer->timeout = srchTimer->timeout - updateTime; }

// When timeout or delete (event_flag == 0)/需要处理的事件 if ( srchTimer->timeout == 0 || srchTimer->event_flag == 0 ) {

// Take out of list if ( prevTimer == NULL ) timerHead = srchTimer->next; else

prevTimer->next = srchTimer->next;

// Setup to free memory/设置要被释放的资源 freeTimer = srchTimer;


ZigBee协议栈任务处理分析笔记.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:浅谈过期药品回收制度

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: