OSAL的运行机理
事件表
函数表
使用查表法来取得事件所对应函数
taskCnt任务总数
taskEvents指向事件表首地址的指针
taskArr事件处理函数数组,每一项都是一个函数指针
由此可以看出,osal是一种基于事件驱动的轮询式操作系统
在使用共享变量时需要保证变量不被其他变量访问,常用关中断的方法,示例
在OSAL.C文件的osal_start_system()方法中可以看到
HAL_ENTER_CRITICAL_SECTION(intState);//关中断
....
HAL_EXIT_CRITICAL_SECTION(intState);//恢复中断
//osal_start_system()函数的示例代码如下:
voidosal_start_system(void)
{
for(;;)//ForeverLoop
{
osal_run_system();
}
}
osal_run_system()函数的示例代码如下:
voidosal_run_system(void)
{
/*事件表中索引*/
uint8idx=0;
#ifndefHAL_BOARD_CC2538
/*更新定时器*/
osalTimeUpdate();
#endif
/*查看硬件方法是否有事件发生*/
Hal_ProcessPoll();
/*循环查看事件表是否有事件发生*/
/*每个二进制位表示一个事件*/
do{
if(tasksEvents[idx])//Taskishighestprioritythatisready.
{
break;
}
}while(++idx if(idx { uint16events; halIntState_tintState; HAL_ENTER_CRITICAL_SECTION(intState); /*读取事件*/ events=tasksEvents[idx]; /*事件标志清零*/ tasksEvents[idx]=0;//CleartheEventsforthistask. HAL_EXIT_CRITICAL_SECTION(intState); /*调用事件处理函数处理*/ activeTaskID=idx; events=(tasksArr[idx])(idx,events); activeTaskID=TASK_NO_TASK; HAL_ENTER_CRITICAL_SECTION(intState); /*将未处理的事件重新放到事件表中*/ /*如何在事件处理函数中返回未处理事件?*/ /*SimpleBLEPeripheral_ProcessEvent*/ tasksEvents[idx]|=events;//Addbackunprocessedeventstothecurrenttask. HAL_EXIT_CRITICAL_SECTION(intState); } #ifdefined(POWER_SAVING) else//Completepassthroughalltaskeventswithnoactivity? { osal_pwrmgr_powerconserve();//Puttheprocessor/systemintosleep } #endif /*Yieldincasecooperativeschedulingisbeingused.*/ #ifdefined(configUSE_PREEMPTION)&&(configUSE_PREEMPTION==0) { osal_task_yield(); } #endif } 如何在事件处理函数中返回未处理的事件 查看SimpleBLEPeripheral.c文件中的SimpleBLEPeripheral_ProcessEvent()函数,原型如下 uint16SimpleBLEPeripheral_ProcessEvent(uint8task_id,uint16events) { VOIDtask_id;//OSALrequiredparameterthatisn'tusedinthisfunction /*检查是否有系统消息任务,有则定义一个消息指针*/ if(events&SYS_EVENT_MSG) { uint8*pMsg; /*检查是否从消息队列中收到数据*/ if((pMsg=osal_msg_receive(simpleBLEPeripheral_TaskID))!=NULL) { /*处理任务信息*/ simpleBLEPeripheral_ProcessOSALMsg((osal_event_hdr_t*)pMsg); //ReleasetheOSALmessage /*释放消息的缓存空间*/ VOIDosal_msg_deallocate(pMsg); } //returnunprocessedevents /*返回未处理的任务标志*/ return(events^SYS_EVENT_MSG); } /*检查是否有启动设务任务*/ if(events&SBP_START_DEVICE_EVT) { //StarttheDevice /*启动设备,括号内为回调函数,来设置要显示的信息或操作*/ VOIDGAPRole_StartDevice(&simpleBLEPeripheral_PeripheralCBs); //StartBondManager /*启动绑定管理函数,处理认证信息和注册任务信息*/ VOIDGAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs); //Settimerforfirstperiodicevent /*设置定时时间,到时后周期事件的任务id被置起*/ osal_start_timerEx(simpleBLEPeripheral_TaskID,SBP_PERIODIC_EVT,SBP_PERIODIC_EVT_PERIOD); /*返回未处理的任务标志*/ return(events^SBP_START_DEVICE_EVT); } /*检查是否有周期任务事件*/ if(events&SBP_PERIODIC_EVT) { //Restarttimer /*如果有周期任务事件*/ if(SBP_PERIODIC_EVT_PERIOD) { /*设置定时时间*/ osal_start_timerEx(simpleBLEPeripheral_TaskID,SBP_PERIODIC_EVT,SBP_PERIODIC_EVT_PERIOD); } //Performperiodicapplicationtask /*处理周期事件中的处理工作*/ performPeriodicTask(); /*返回未处理的任务标志*/ return(events^SBP_PERIODIC_EVT); } //Discardunknownevents /*未知的任务事件清零*/ return0; } OSAL消息队列 事件+外设数据组装成消息----->存放到消息队列--->事件处理函数从消息队列中读取消息k typedefstruct { uint8event; uint8status; }osal_event_hdr_t; OSAL添加新任务 在OSAL_SimpleBLEPeripheral.c文件中可以看到: tasksArr[]存放所有任务的事件处理函数的地址 osalInitTasks()任务初始化函数,给每一个任务分配id 添加新任务的操作: 1新任务的初始化函数 constpTaskEventHandlerFntasksArr[]= { LL_ProcessEvent,//task0 Hal_ProcessEvent,//task1 HCI_ProcessEvent,//task2 #ifdefined(OSAL_CBTIMER_NUM_TASKS) OSAL_CBTIMER_PROCESS_EVENT(osal_CbTimerProcessEvent),//task3 #endif L2CAP_ProcessEvent,//task4 GAP_ProcessEvent,//task5 GATT_ProcessEvent,//task6 SM_ProcessEvent,//task7 GAPRole_ProcessEvent,//task8 GAPBondMgr_ProcessEvent,//task9 GATTServApp_ProcessEvent,//task10 SimpleBLEPeripheral_ProcessEvent//task11 }; 2新任务的事件处理函数 voidosalInitTasks(void) { uint8taskID=0; tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt); osal_memset(tasksEvents,0,(sizeof(uint16)*tasksCnt)); /*LLTask*/ LL_Init(taskID++); /*HalTask*/ Hal_Init(taskID++); /*HCITask*/ HCI_Init(taskID++); #ifdefined(OSAL_CBTIMER_NUM_TASKS) /*CallbackTimerTasks*/ osal_CbTimerInit(taskID); taskID+=OSAL_CBTIMER_NUM_TASKS; #endif /*L2CAPTask*/ L2CAP_Init(taskID++); /*GAPTask*/ GAP_Init(taskID++); /*GATTTask*/ GATT_Init(taskID++); /*SMTask*/ SM_Init(taskID++); /*Profiles*/ GAPRole_Init(taskID++); GAPBondMgr_Init(taskID++); GATTServApp_Init(taskID++); /*Application*/ SimpleBLEPeripheral_Init(taskID); } 注: 1tassArr[]数组里各事件处理函数的排列顺序要与osalInitTasks()函数中调用各任务初 始化函数的顺序保持一致 2osalInitTasks()分配的id.需要任务定义一个全局变量来保存 OSAL应用编程接口 消息管理 任务同步 时间管理 中断管理 任务管理 内存管理 电源管理 非易失性闪存管理 消处管理接口的定义在osal.h文件中可以看到,示例代码如下: /***MessageManagement***/ /***消息管理API***/ /* *TaskMessageAllocation *为消息分配缓存空间 */ externuint8*osal_msg_allocate(uint16len); /* *TaskMessageDeallocation *为消息释放缓存空间 */ externuint8osal_msg_deallocate(uint8*msg_ptr); /* *SendaTaskMessage *任务发送消息到消息队列 */ externuint8osal_msg_send(uint8destination_task,uint8*msg_ptr); /* *PushaTaskMessagetoheadofqueue *将任务消息压入栈顶 */ externuint8osal_msg_push_front(uint8destination_task,uint8*msg_ptr); /* *ReceiveaTaskMessage *任务从消息队列中读取属于自已的消息 */ externuint8*osal_msg_receive(uint8task_id); /* *FindinplaceamatchingTaskMessage/Event. */ externosal_event_hdr_t*osal_msg_find(uint8task_id,uint8event); /* *EnqueueaTaskMessage */ externvoidosal_msg_enqueue(osal_msg_q_t*q_ptr,void*msg_ptr); /* *EnqueueaTaskMessageUptoMax */ externuint8osal_msg_enqueue_max(osal_msg_q_t*q_ptr,void*msg_ptr,uint8max); /* *DequeueaTaskMessage */ externvoid*osal_msg_dequeue(osal_msg_q_t*q_ptr); /* *PushaTaskMessagetoheadofqueue */ externvoidosal_msg_push(osal_msg_q_t*q_ptr,void*msg_ptr); /* *ExtractandremoveaTaskMessagefromqueue */ externvoidosal_msg_extract(osal_msg_q_t*q_ptr,void*msg_ptr,void*prev_ptr); 任务同步管理接口在文件OSAL.h中定义,示例代码如下: /***TaskSynchronization***/ /* *SetaTaskEvent *设置任务事件 */ externuint8osal_set_event(uint8task_id,uint16event_flag); /* *ClearaTaskEvent *清除任务事件 */ externuint8osal_clear_event(uint8task_id,uint16event_flag); 时间管理接口在文件OSAL_Timers.h中定义,示例代码如下: /* *InitializationfortheOSALTimerSystem. */ externvoidosalTimerInit(void); /* *SetaTimer *设置定时时间,到时后,相应事件被设置 */ externuint8osal_start_timerEx(uint8task_id,uint16event_id,uint32timeout_value); /* *Setatimerthatreloadsitself. */ externuint8osal_start_reload_timer(uint8taskID,uint16event_id,uint32timeout_value); /* *StopaTimer *停止定时器 */ externuint8osal_stop_timerEx(uint8task_id,uint16event_id); /* *GetthetickcountofaTimer. */ externuint32osal_get_timeoutEx(uint8task_id,uint16event_id); /* *SimulatedTimerInterruptServiceRoutine */ externvoidosal_timer_ISR(void); /* *Adjusttimertables */ externvoidosal_adjust_timers(void); /* *Updatetimertables */ externvoidosalTimerUpdate(uint32updateTime); /* *Countactivetimers */ externuint8osal_timer_num_active(void); /* *Setthehardwaretimerinterruptsforsleepmode. *ThesefunctionsshouldonlybecalledinOSAL_PwrMgr.c */ externvoidosal_sleep_timers(void); externvoidosal_unsleep_timers(void); /* *Readthesystemclock-returnsmilliseconds */ externuint32osal_GetSystemClock(void); /* *GetthenextOSALtimerexpiration. *ThisfunctionshouldonlybecalledinOSAL_PwrMgr.c */ externuint32osal_next_timeout(void); 中断管理接口定义在soal.h文件中,示例代码如下: /***InterruptManagement***/ /* *RegisterInterruptServiceRoutine(ISR) */ externuint8osal_isr_register(uint8interrupt_id,void(*isr_ptr)(uint8*)); /* *EnableInterrupt *开启中断 */ externuint8osal_int_enable(uint8interrupt_id); /* *DisableInterrupt *关闭中断 */ externuint8osal_int_disable(uint8interrupt_id); 任务管理接口定义在soal.h文件中, /***TaskManagement***/ /* *InitializetheTaskSystem *初始化osal,第一个被调用的函数 */ externuint8osal_init_system(void); /* *SystemProcessingLoop */ #ifdefined(ZBIT) extern__declspec(dllexport)voidosal_start_system(void); #else /*包含一个无限循环,查询事件,执行处理函数,*/ externvoidosal_start_system(void); #endif /* *OnePassThroutheOSALProcessingLoop */ externvoidosal_run_system(void); /* *GettheactivetaskID *取得任务id */ externuint8osal_self(void); 内存管理接口,定义在OSAL_Memory.h文件中定义 /* *Initializememorymanager. */ voidosal_mem_init(void); /* *Setupefficientsearchforthefirstfreeblockofheap. */ voidosal_mem_kick(void); /* *Allocateablockofmemory. */ #ifdefDPRINTF_OSALHEAPTRACE void*osal_mem_alloc_dbg(uint16size,constchar*fname,unsignedlnum); #defineosal_mem_alloc(_size)osal_mem_alloc_dbg(_size,__FILE__,__LINE__) #else/*DPRINTF_OSALHEAPTRACE*/ /*分配指定大小的缓冲区*/ void*osal_mem_alloc(uint16size); #endif/*DPRINTF_OSALHEAPTRACE*/ /* *Freeablockofmemory. */ #ifdefDPRINTF_OSALHEAPTRACE voidosal_mem_free_dbg(void*ptr,constchar*fname,unsignedlnum); #defineosal_mem_free(_ptr)osal_mem_free_dbg(_ptr,__FILE__,__LINE__) #else/*DPRINTF_OSALHEAPTRACE*/ /*释放分配的缓冲区*/ voidosal_mem_free(void*ptr); #endif/*DPRINTF_OSALHEAPTRACE*/ #if(OSALMEM_METRICS) /* *Returnthemaximumnumberofblockseverallocatedatonce. */ uint16osal_heap_block_max(void); /* *Returnthecurrentnumberofblocksnowallocated. */ uint16osal_heap_block_cnt(void); /* *Returnthecurrentnumberoffreeblocks. */ uint16osal_heap_block_free(void); /* *Returnthecurrentnumberofbytesallocated. */ uint16osal_heap_mem_used(void); #endif #ifdefined(ZTOOL_P1)||defined(ZTOOL_P2) /* *Returnthehighestnumberofbyteseverusedintheheap. */ uint16osal_heap_high_water(void); #endif 电源管理接口,定义在OSAL_PwrMgr.h文件中,示例代码如下 /* *Initializethepowermanagementsystem. *ThisfunctioniscalledfromOSAL. * */ externvoidosal_pwrmgr_init(void); /* *Thisfunctioniscalledbyeachtasktostatewhetherornotthis *taskwantstoconservepower.Thetaskwillcallthisfunctionto *votewhetheritwantstheOSALtoconservepoweroritwantsto *holdoffonthepowersavings.Bydefault,whenataskiscreated, *itsownpowerstateissettoconserve.Ifthetaskalwayswants *toconversepower,itdoesn'tneedtocallthisfunctionatall. *Itisimportantforthetaskthatchangedthepowermanagertask *statetoPWRMGR_HOLDtoswitchbacktoPWRMGR_CONSERVEwhenthe *holdperiodends. */ externuint8osal_pwrmgr_task_state(uint8task_id,uint8state); /* *Thisfunctioniscalledonpower-up,wheneverthedevicecharacteristic *change(ex.Batterybackedcoordinator).Thisfunctionworkswiththetimer *tosetHAL'spowermanagersleepstatewhenpowersavingisentered. *ThisfunctionshouldbecalledformHALinitialization.Afterpowerup *initialization,itshouldonlybecalledfromNWKorZDO. */ externvoidosal_pwrmgr_device(uint8pwrmgr_device); /* *ThisfunctioniscalledfromthemainOSALloopwhenthereare *noeventsscheduledandshouldn'tbecalledfromanywhereelse. */ externvoidosal_pwrmgr_powerconserve(void); 非易失性闪存管理接口定义没找到???????????? staticuint8initNV(void); staticvoidsetActivePage(uint8pg); staticvoidsetXferPage(void); staticvoiderasePage(uint8pg); staticvoidcleanErasedPage(uint8pg); staticvoidfindOffset(void); staticvoidcompactPage(uint8pg); staticvoidwriteWord(uint8pg,uint16offset,uint8*pBuf); staticvoidwriteWordM(uint8pg,uint16offset,uint8*pBuf,osalSnvLen_tcnt);
osal.h文件中定义了消息头,示例代码如下: