ble学习笔记九----------ble协议栈之OSAL的运行机理

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



osal.h文件中定义了消息头,示例代码如下:

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

你可能感兴趣的:(ble学习笔记九----------ble协议栈之OSAL的运行机理)