OSAL概述
OSAL是操作系统抽象层操作系统抽象层),支持多任务处理。 现在将运行BLE协议栈、配置文件和所有app应用程序app )。 虽然这不是传统意义上的操作系统,但它实现了一些类似操作系统的功能。 为了方便,以下简称OSAL系统。
1、OSAL的简单流程
初始化完成后,在app的init末尾启动计时器或直接set任务事件START_DEVICE_EVT,超时后进入app回调函数START_DEVICE_EVT事件分支处理,在该分支中
OSAL系统运行,判断当前是否有任务事件需要处理,如果有,调用相应的回调函数进行处理,结束后复位定时器等待超时,如果没有任务事件,进入休眠状态,等待唤醒。
2、OSAL的主函数
这两个程序都从main函数开始。 在单片机程序中,一般顺序如下。
时钟初始化——兼容外围设备初始化——系统密钥参数初始化——进入死循环处理;
在OSAL的main函数中,这些过程也是:
133) )、)、)、)、)、)、I )、ii )、ii )、ii )、ii )、ii )、ii )等。 @ briefstartofapplication.1011 * 1213 * @ param none 1415 * 1617 * @ return none 1819 * * * * * * * * * * * * * * * 2333/* initialzethehaldriver */34 haldriverinit ; 5336/* initializenvsystem */37 osal _ snv _ init ; 339/* initialize ll */4041/* initializetheoperatingsystem */42 osal _ init _ system ; 344/* enable interrupts */45h al _ enable _ interrupts ; 647//finalboardinitialization 48 init board ob _ ready ); 950#ifdefinedpower_saving ) 5152osal_pwrmgr_device ) pwrmgr_battery; 354 # endif 5556/* startosal */57 osal _ start _ system ; //No Return from here58 59 return 0; 6061 ) 62636465
分析:
HAL_BOARD_INIT ; //初始化水晶振动和预读程序
initboardob_cold ); main函数中有两个InitBoard 这是第一次初始化,此时OSAL还没有启动,IO和一些系统级寄存器已经初始化,电脑上的BIOS似乎正在准备启动系统,个人识别,欢迎指正
HalDriverInit ; //这里硬件初始化、计时器、模数转换、LCD、LED、KEY等
osal_snv_init ; //初始化存储区域
osal_init_system ; 初始化//OSAL。 系统初始化、内存初始化、消息队列初始化、计时器初始化、电源管理初始化和APP应用程序初始化都由此函数完成。 用OSAL编程。 我们的任务app的初始化程序通过这里的app应用程序的初始化来进行。 每个APP应用程序都位于OSAL中,只有一个全局唯一标识符。 也就是说,这是本任务的taskID。 在此分配。 在这里
这里分配的taskID
initboardob_ready )。
; //第二次调用该函数初始化,此时系统已启动,在此处可将硬件
回调函数注册至系统~~
osal_pwrmgr_device PWRMGR_BATTERY ); //如果定义了 POWER_SAVING,电源管理启动
osal_start_system); //进入系统主循环
以上,各种初始化与设置,然后进入loop,,,,,,,,,,
for ; ; )
{
//loop
}
3、OSAL的主循环
在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 void12 *13 * @return none14 */15 void osal_run_system void )16 {17 uint8 idx = 0;18 19 #ifndef HAL_BOARD_CC253820 osalTimeUpdate);21 #endif22 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_SECTIONintState);38 events = tasksEvents[idx];39 tasksEvents[idx] = 0; // Clear the Events for this task.40 HAL_EXIT_CRITICAL_SECTIONintState);41 42 activeTaskID = idx;43 events = tasksArr[idx]) idx, events );44 activeTaskID = TASK_NO_TASK;45 46 HAL_ENTER_CRITICAL_SECTIONintState);47 tasksEvents[idx] |= events; // Add back unprocessed events to the current task.48 HAL_EXIT_CRITICAL_SECTIONintState);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 sleep54 }55 #endif56 57 /* Yield in case cooperative scheduling is being used. */58 #if defined configUSE_PREEMPTION) && configUSE_PREEMPTION == 0)59 {60 osal_task_yield);61 }62 #endif63 }
分析这个函数之前先搞明白几个主要的变量,
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方式进行定义,如0x0001、0x0002、0x0004……这样做可以使 存在多个数据同时需要处理时,在处理完某一事件后,返回主循环,判断继续处理下一事件。每一个任务都包含一个系统事件SYS_EVENT_MSG,因此每个任务最多可以有15个自有事件,其在init时初始化为0;
3) tasksArr[],函数指针数组,该指针数组元素为函数指针,具体为各模块事件回调函数,编写完本模块事件回调函数之后,按照本模块ID,将回调注册至此处,在主循环中准备调用。
在本函数中,do{…}while);循环判断是否存在待处理的任务事件,即tasksEvents[idx]是否为空,若存在则break,并进入后续if语句,先保存当前事件,并清空事件标志,调用tasksArr[idx]) idx, events );处理任务事件并返回,此时event使用位图方法定义的好处就体现了一点,一般在回调函数返回时,会return event ^ currntEVENT; 异或操作只处理当前位,表明当前事件处理完毕,若其他位不为0,则表示该任务还有其他事件待处理;回调函数返回后,保存事件标志位,进入下一次轮询。
转载于:https://www.cnblogs.com/zzmx/p/4974731.html