Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2263259
  • 博文数量: 187
  • 博客积分: 1457
  • 博客等级: 上尉
  • 技术积分: 2423
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-13 09:41
个人简介

如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.

文章分类

全部博文(187)

文章存档

2017年(2)

2016年(2)

2015年(7)

2014年(13)

2013年(80)

2012年(83)

分类: 嵌入式

2013-04-19 17:26:00

OSAL系统主循环函数:

void osal_start_system( void )

{

    #if !defined ( ZBIT )  //不知道是什么东西

      for(;;)   // Forever Loop

    #endif

  {

    uint8 idx = 0;

Hal_ProcessPoll(); 

// This replaces MT_SerialPoll() and osal_check_timer().

 //轮询TIMERUART

轮询UARTTIMER,涉及HAL,晚点总结,添加串口相关代码就是在这里。

初始化时由osal_memset()设为0只要不为空类型NULL,即有相对应任务事件发生,就break跳出循环体,通过下面的程序进行任务事件处理。如果为空,执行判断语句,即idx自增,再返回轮询有无各层的任务事件发生。如果执行完循环语句都没有检测到有事件发生,idx=7,进入睡眠。对于本例子来说,任务数组里只有七个任务,tasksEvents[0]tasksEvents[6]tasksEvents[6]就是用户自已添加的任务,idx随着用户添加任务的增多而增大

    do {

      if (tasksEvents[idx])  // Task is highest priority that is ready.

      {                     

        break;             

      }

} while (++idx < tasksCnt); //tasksCnt=7

(针对本例子,随着用户应用任务增多而增大)

    if (idx < tasksCnt)

    {

      uint16 events;

      halIntState_t intState;  //中断位状态

      HAL_ENTER_CRITICAL_SECTION(intState);  

//中断临界状态:保存先前中断状态,然后关中断

      events = tasksEvents[idx];

 //uint16 events;对应有事件发生的任务的数组

      tasksEvents[idx] = 0; 

// Clear the Events for this task.  NULL

      HAL_EXIT_CRITICAL_SECTION(intState);

 //跳出中断临界状态:恢复先前中断状态 

/***********************************************************************************************/

                #define HAL_ENABLE_INTERRUPTS()            st( EA = 1; )  //开中断

                #define HAL_DISABLE_INTERRUPTS()           st( EA = 0; )  //关中断

                #define HAL_INTERRUPTS_ARE_ENABLED()    (EA)

                typedef unsigned char halIntState_t;  //中断位状态

                //中断临界状态:把原先中断状态EA赋给X,然后关中断;以便后面可以恢复原先的中断状态

                #define HAL_ENTER_CRITICAL_SECTION(x)    st( x = EA;  HAL_DISABLE_INTERRUPTS(); )

                //跳出上面的中断临界状态,恢复先前的中断状态          
              #define HAL_EXIT_CRITICAL_SECTION(x)    st( EA = x; )

                //中断临界状态以及跳出临界状态的全过程:

           #define HAL_CRITICAL_STATEMENT(x)       st( halIntState_t s; HAL_ENTER_CRITICAL_SECTION(s); x;HAL_EXIT_CRITICAL_SECTION(s); )

                st()函数,定义在hal_defs.h

                #define st(x)      do { x } while (__LINE__ == -1)  

                临界状态是操作系统为了防止数据发生竞争而采取的一种保护策略。具体的原理在linux kernel里面有详细介绍
     /***********************************************************************************************/

      events = (tasksArr[idx])( idx, events ); 

 //调用相对应的任务事件处理函数处理,各类事件处理函M(task_id,event)返回的都是这个任务未被处理的事件。

      HAL_ENTER_CRITICAL_SECTION(intState);

      tasksEvents[idx] |= events;   

        // Add back unprocessed events to the current task.

        //把刚才返回未处理的任务事件添加加当前任务中再进行处理,跳出此if(idx < tasksCnt)循环再进行if (tasksEvents[idx])判断并处理)

      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

    }

}


/***********************************************************************************************/

接下来就是事件和任务处理函数,涉及到指针数组和函数指针的问题,最好先看看C语言教程。

//typedef unsigned short  uint16;

//typedef unsigned char   uint8;

tasksEvents[ ]是一个事件数组,其元素对应着事件值uint16类型的),也即是事件。但是在OSAL_SampleApp.c下有这么一个声明:uint16*tasksEvents;所以很多人将其误认为事件指针的数组从程序后面来看,这里虽然定义了tasksEvents为指针,但是在实际使用过程中将其作为一个uint16类型的数组来使用的(tasksEvents[idx]例如:uint16 a[],是定义了uint16类型的a数组。如果我定义了uint16 *a;然后利用a[0],a[1]来赋值使用,这样a就变成了一个uint16类型的数组,但是a本身还是一个指针,指向a[]的首地址,也指向a[0]的地址,a=&a[0]a++就是&a[1]但是a[idx](也就是*(a+idx)就是一个地道的uint16数值了,也就是事件本身了。关于这点如果不明白,可以参考一下谭浩强的指针和数组之间的关系。
对于本例子来说内部各元素即tasksEvents[0]tasksEvents[6]tasksEvents[idx]是就是事件)。

/***********************************************************************************************/

        events = (tasksArr[idx])( idx, events );任务idx的事件处理函数

        首先看下对tasksArr[ ]的定义:

            const pTaskEventHandlerFn tasksArr[ ] =

            //数组tasksArr[ ]7个元素(MT defined)

                                                                                    {

                                                                                          macEventLoop,   //MAC层任务事件处理函数

                                                                                          nwk_event_loop,  //NWK层任务事件处理函数

                                                                                          Hal_ProcessEvent,  //PHY层事件处理函数

                                                                                            #if defined( MT_TASK )

                                                                                              MT_ProcessEvent, //MT任务事件处理函数

                                                                                            #endif

                                                                                          APS_event_loop,  //APS层任务事件处理函数

                                                                                          ZDApp_event_loop,  //ZDO任务事件处理函数

                                                                                          SampleApp_ProcessEvent  //用户应用任务事件处理函数

                                                                                        };

再来看下对 pTaskEventHandlerFn的定义:(OSAL_Tasks.h中)
/***********************************************************************************************/

typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );

typedef,把pTaskEventHandlerFn声明成一种函数指针类型的别名,这种函数指针指向M(task_id,event)这种类型的函数
即各任务的事件处理函数。
其实我们正常定义的函数,其函数名就是一种指针,所以
tasksArr[ ]就是一个指针数组,数组里面的元素就是函数指针(pTaskEventHandlerFn类型的),或者说就是函数名称这样tasksArr[ ]就是一个按照idx顺序排列的函数数组了。    
    如果调用相对应的函数,直接使用
tasksArr[idx]task_id,event就行了,也即是调用相应的函数。
          
这里如果不明白,请看看可以找到谭浩强的那本C语言书籍,具体看看。

OSAL_SampleApp.c中对tasksArr[ ]的定义我们可以知道macEventLoopnwk_event_loop……SampleApp_ProcessEvent这些元素都是函数名称,也即是函数指针变量,最终都是指向M(task_id,event)这种类型的函数,也就是各层的事件处理函数。
/***********************************************************************************************/

参考文章为 http://wjf88223.blog.163.com。


阅读(2005) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

abclixu1232013-05-15 22:39:24

好。