OSAL概述

OSAL概述

OSALOperating System Abstraction Layer,即操作系统抽象层,支持多任务运行,其中BLE协议栈、配置文件以及所有的应用程序(app)都在其上运行,它并不是一个传统意义上的操作系统,但是实现了部分类似操作系统的功能,为了方便,下面简称OSAL系统。

 

 

1、OSAL简要流程

 

 

 

初始化完成后,在appinit最后一般会启动一个定时器或者直接set一个任务事件START_DEVICE_EVT,超时后进入app回调函数START_DEVICE_EVT事件分支处理,在该分支中启动具体的信息采集、数据处理、数据显示或发送等定时任务。

OSAL系统工作,判断当前是否存在待处理的任务事件,有,则调用对应的回调函数进行处理,并在结束后重新设定定时器等待超时,若没有任务事件,则进入休眠状态,等待唤醒。

 

 

2OSALmain函数

 

任何一个程序都由main函数起,单片机程序中,一般顺序为:

时钟初始化——>相应外设初始化——>系统关键参数初始化——>进入死循环处理;

OSALmain函数中,同样也是这些流程:

 1  
 2 
 3 /**************************************************************************************************
 4 
 5  * @fn          main
 6 
 7  *
 8 
 9  * @brief       Start of application.
10 
11  *
12 
13  * @param       none
14 
15  *
16 
17  * @return      none
18 
19  **************************************************************************************************
20 
21  */
22 
23 int main(void)
24 
25 {
26 
27   /* Initialize hardware */
28   HAL_BOARD_INIT();
29 
30   // Initialize board I/O
31   InitBoard( OB_COLD );
32 
33   /* Initialze the HAL driver */
34   HalDriverInit();
35 
36   /* Initialize NV system */
37   osal_snv_init();
38 
39   /* Initialize LL */
40 
41   /* Initialize the operating system */
42   osal_init_system();
43 
44   /* Enable interrupts */
45   HAL_ENABLE_INTERRUPTS(); 
46 
47   // Final board initialization
48   InitBoard( OB_READY );
49 
50   #if defined ( POWER_SAVING )
51 
52     osal_pwrmgr_device( PWRMGR_BATTERY );
53 
54   #endif
55 
56   /* Start OSAL */
57   osal_start_system(); // No Return from here
58 
59   return 0;
60 
61 }
62 
63  
64 
65  

 

 

解析:

 HAL_BOARD_INIT(); //初始化晶振及预读取程序 

 

 InitBoard( OB_COLD ); //main函数中有两处InitBoard();此为第一次初始化,此时OSAL   还未启动,初始化IO及一些系统级寄存器,类似电脑上的BIOS   为系统的启动做准备,个人认识,欢迎指正。

 

 HalDriverInit(); //此处进行硬件初始化,定时器、AD转换、LCDLEDKEY

 

 osal_snv_init(); //初始化存储区域

 

 osal_init_system(); //初始化OSAL,此处系统初始化,内存初始化、消息队列初始  化、定时器初始化、电源管理初始化及应用程序初始化均在该  函数中进行,在OSAL上编程,我们的任务app的初始化程序  在此处的应用程序初始化中进行,每一个应用程序在OSAL  有且只有一个全局唯一标识,即本任务的taskID,在这里进行  分配,在之后的主循环中进行任务分配与事件处理时,使用的

 即为这里分配的taskID

 

 InitBoard( OB_READY ); //第二次调用该函数初始化,此时系统已启动,在此处可将硬件

  回调函数注册至系统~~

 

 osal_pwrmgr_device( PWRMGR_BATTERY ); //如果定义了 POWER_SAVING,电源管理启动

 

 osal_start_system(); //进入系统主循环

 

以上,各种初始化与设置,然后进入loop,,,,,,,,,,

for( ; ; )

{

//loop

}

 

 

 

3OSAL的主循环

 

osal_start_system() 中调用函数osal_run_system()

 1 /*********************************************************************
 2  * @fn      osal_run_system
 3  *
 4  * @brief
 5  *
 6  *   This function will make one pass through the OSAL taskEvents table
 7  *   and call the task_event_processor() function for the first task that
 8  *   is found with at least one event pending. If there are no pending
 9  *   events (all tasks), this function puts the processor into Sleep.
10  *
11  * @param   void
12  *
13  * @return  none
14  */
15 void osal_run_system( void )
16 {
17   uint8 idx = 0;
18 
19 #ifndef HAL_BOARD_CC2538
20   osalTimeUpdate();
21 #endif
22 
23   Hal_ProcessPoll();
24 
25   do {
26     if (tasksEvents[idx])  // Task is highest priority that is ready.
27     {
28       break;
29     }
30   } while (++idx < tasksCnt);
31 
32   if (idx < tasksCnt)
33   {
34     uint16 events;
35     halIntState_t intState;
36 
37     HAL_ENTER_CRITICAL_SECTION(intState);
38     events = tasksEvents[idx];
39     tasksEvents[idx] = 0;  // Clear the Events for this task.
40     HAL_EXIT_CRITICAL_SECTION(intState);
41 
42     activeTaskID = idx;
43     events = (tasksArr[idx])( idx, events );
44     activeTaskID = TASK_NO_TASK;
45 
46     HAL_ENTER_CRITICAL_SECTION(intState);
47     tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
48     HAL_EXIT_CRITICAL_SECTION(intState);
49   }
50 #if defined( POWER_SAVING )
51   else  // Complete pass through all task events with no activity?
52   {
53     osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
54   }
55 #endif
56 
57   /* Yield in case cooperative scheduling is being used. */
58 #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
59   {
60     osal_task_yield();
61   }
62 #endif
63 }

 

 

分析这个函数之前先搞明白几个主要的变量,

uint16 *tasksEvents;

 

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

const pTaskEventHandlerFn tasksArr[] = 

{

//........

};

 

uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );

 

(1) tasksCnt,即OSAL内任务个数; 

(2) tasksEvents,从定义上看,short类型指针,值域0x0000 ~ 0xFFFF,事实上,每个task只允许存在16个事件类型,在使用宏定义事件类型时,采用bit map方式进行定义,如0x00010x00020x0004……这样做可以使 存在多个数据同时需要处理时,在处理完某一事件后,返回主循环,判断继续处理下一事件。每一个任务都包含一个系统事件SYS_EVENT_MSG,因此每个任务最多可以有15个自有事件,其在init时初始化为0

(3) tasksArr[],函数指针数组,该指针数组元素为函数指针,具体为各模块事件回调函数,编写完本模块事件回调函数之后,按照本模块ID,将回调注册至此处,在主循环中准备调用。

 

在本函数中,do{...}while();循环判断是否存在待处理的任务事件,即tasksEvents[idx]是否为空,若存在则break,并进入后续if语句,先保存当前事件,并清空事件标志,调用(tasksArr[idx])( idx, events );处理任务事件并返回,此时event使用位图方法定义的好处就体现了一点,一般在回调函数返回时,会return event ^ currntEVENT; 异或操作只处理当前位,表明当前事件处理完毕,若其他位不为0,则表示该任务还有其他事件待处理;回调函数返回后,保存事件标志位,进入下一次轮询。

posted on 2015-11-18 15:35  vi_cc  阅读(7804)  评论(0编辑  收藏  举报

导航