Zigbee协议栈中OSAL的运行机理
OSAL的運行機理
?
?
?
事件表
函數表
使用查表法來取得事件所對應函數?
?
?
taskCnt??任務總數
taskEvents?指向事件表首地址的指針
taskArr?事件處理函數數組,每一項都是一個函數指針
?
由此可以看出,osal是一種基于事件驅動?的輪詢式操作系統
?
在使用共享變量時需要保證變量不被其他變量訪問,常用關中斷的方法,示例
在OSAL.C文件的osal_start_system()方法中可以看到
?HAL_ENTER_CRITICAL_SECTION(intState);//關中斷
??....
?HAL_EXIT_CRITICAL_SECTION(intState);//恢復中斷
?
?
?
?
?
//osal_start_system()函數的示例代碼如下:
void?osal_start_system(?void?)
{
???for(;;)??//?Forever?Loop
???{
????osal_run_system();
??}
}
?
?
osal_run_system()函數的示例代碼如下:
void?osal_run_system(?void?)
{
??/*事件表中索引*/
??uint8?idx?=?0;
?
#ifndef?HAL_BOARD_CC2538
??/*更新定時器*/
??osalTimeUpdate();
#endif
??/*查看硬件方法是否有事件發生*/
??Hal_ProcessPoll();
??
??/*循環查看事件表是否有事件發生?*/
??/*每個二進制位表示一個事件*/
??do?{
????if?(tasksEvents[idx])??//?Task?is?highest?priority?that?is?ready.
????{
??????break;
????}
??}?while?(++idx?<?tasksCnt);
?
??if?(idx?<?tasksCnt)
??{
????uint16?events;
????halIntState_t?intState;
?
????HAL_ENTER_CRITICAL_SECTION(intState);
????/*讀取事件*/
????events?=?tasksEvents[idx];
????/*事件標志清零*/
????tasksEvents[idx]?=?0;??//?Clear?the?Events?for?this?task.
????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;??//?Add?back?unprocessed?events?to?the?current?task.
????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
?
??/*?Yield?in?case?cooperative?scheduling?is?being?used.?*/
#if?defined?(configUSE_PREEMPTION)?&&?(configUSE_PREEMPTION?==?0)
??{
????osal_task_yield();
??}
#endif
}
?
?
如何在事件處理函數中返回未處理的事件
查看SimpleBLEPeripheral.c文件中的SimpleBLEPeripheral_ProcessEvent()函數,原型如下
uint16?SimpleBLEPeripheral_ProcessEvent(?uint8?task_id,?uint16?events?)
{
?
??VOID?task_id;?//?OSAL?required?parameter?that?isn't?used?in?this?function
?
??/*檢查是否有系統消息任務,有則定義一個消息指針*/
??if?(?events?&?SYS_EVENT_MSG?)
??{
????uint8?*pMsg;
????/*檢查是否從消息隊列中收到數據*/
????if?(?(pMsg?=?osal_msg_receive(?simpleBLEPeripheral_TaskID?))?!=?NULL?)
????{
??????/*處理任務信息*/
??????simpleBLEPeripheral_ProcessOSALMsg(?(osal_event_hdr_t?*)pMsg?);
?
??????//?Release?the?OSAL?message
??????/*釋放消息的緩存空間*/
??????VOID?osal_msg_deallocate(?pMsg?);
????}
?
????//?return?unprocessed?events
????/*返回未處理的任務標志*/
????return?(events?^?SYS_EVENT_MSG);
??}
??/*檢查是否有啟動設務任務*/
??if?(?events?&?SBP_START_DEVICE_EVT?)
??{
????//?Start?the?Device
????/*啟動設備,括號內為回調函數,來設置要顯示的信息或操作*/
????VOID?GAPRole_StartDevice(?&simpleBLEPeripheral_PeripheralCBs?);
?
????//?Start?Bond?Manager
????/*啟動綁定管理函數,處理認證信息和注冊任務信息*/
????VOID?GAPBondMgr_Register(?&simpleBLEPeripheral_BondMgrCBs?);
?
????//?Set?timer?for?first?periodic?event
????/*設置定時時間,到時后周期事件的任務id被置起*/
????osal_start_timerEx(?simpleBLEPeripheral_TaskID,?SBP_PERIODIC_EVT,?SBP_PERIODIC_EVT_PERIOD?);
????/*返回未處理的任務標志*/
????return?(?events?^?SBP_START_DEVICE_EVT?);
??}
??/*檢查是否有周期任務事件*/
??if?(?events?&?SBP_PERIODIC_EVT?)
??{
????//?Restart?timer
????/*如果有周期任務事件*/
????if?(?SBP_PERIODIC_EVT_PERIOD?)
????{
??????/*設置定時時間*/
??????osal_start_timerEx(?simpleBLEPeripheral_TaskID,?SBP_PERIODIC_EVT,?SBP_PERIODIC_EVT_PERIOD?);
????}
?
????//?Perform?periodic?application?task
????/*處理周期事件中的處理工作*/
????performPeriodicTask();
????/*返回未處理的任務標志*/
????return?(events?^?SBP_PERIODIC_EVT);
??}
?
??//?Discard?unknown?events
??/*未知的任務事件清零*/
??return?0;
}
?
?
OSAL消息隊列
事件+外設數據組裝成消息----->存放到消息隊列--->事件處理函數從消息隊列中讀取消息k
osal.h文件中定義了消息頭,示例代碼如下:
typedef?struct
{
??uint8??event;
??uint8??status;
}?osal_event_hdr_t;
?
OSAL添加新任務
在OSAL_SimpleBLEPeripheral.c文件中可以看到:
tasksArr[]??存放所有任務的事件處理函數的地址
osalInitTasks()?任務初始化函數,給每一個任務分配id?
?
添加新任務的操作:
1?新任務的初始化函數
const?pTaskEventHandlerFn?tasksArr[]?=
{
??LL_ProcessEvent,??????????????????????????????????????????????????//?task?0
??Hal_ProcessEvent,?????????????????????????????????????????????????//?task?1
??HCI_ProcessEvent,?????????????????????????????????????????????????//?task?2
#if?defined?(?OSAL_CBTIMER_NUM_TASKS?)
??OSAL_CBTIMER_PROCESS_EVENT(?osal_CbTimerProcessEvent?),???????????//?task?3
#endif
??L2CAP_ProcessEvent,???????????????????????????????????????????????//?task?4
??GAP_ProcessEvent,?????????????????????????????????????????????????//?task?5
??GATT_ProcessEvent,????????????????????????????????????????????????//?task?6
??SM_ProcessEvent,??????????????????????????????????????????????????//?task?7
??GAPRole_ProcessEvent,?????????????????????????????????????????????//?task?8
??GAPBondMgr_ProcessEvent,??????????????????????????????????????????//?task?9
??GATTServApp_ProcessEvent,?????????????????????????????????????????//?task?10
??SimpleBLEPeripheral_ProcessEvent??????????????????????????????????//?task?11
};
2?新任務的事件處理函數
void?osalInitTasks(?void?)
{
??uint8?taskID?=?0;
?
??tasksEvents?=?(uint16?*)osal_mem_alloc(?sizeof(?uint16?)?*?tasksCnt);
??osal_memset(?tasksEvents,?0,?(sizeof(?uint16?)?*?tasksCnt));
?
??/*?LL?Task?*/
??LL_Init(?taskID++?);
?
??/*?Hal?Task?*/
??Hal_Init(?taskID++?);
?
??/*?HCI?Task?*/
??HCI_Init(?taskID++?);
?
#if?defined?(?OSAL_CBTIMER_NUM_TASKS?)
??/*?Callback?Timer?Tasks?*/
??osal_CbTimerInit(?taskID?);
??taskID?+=?OSAL_CBTIMER_NUM_TASKS;
#endif
?
??/*?L2CAP?Task?*/
??L2CAP_Init(?taskID++?);
?
??/*?GAP?Task?*/
??GAP_Init(?taskID++?);
?
??/*?GATT?Task?*/
??GATT_Init(?taskID++?);
?
??/*?SM?Task?*/
??SM_Init(?taskID++?);
?
??/*?Profiles?*/
??GAPRole_Init(?taskID++?);
??GAPBondMgr_Init(?taskID++?);
?
??GATTServApp_Init(?taskID++?);
?
??/*?Application?*/
??SimpleBLEPeripheral_Init(?taskID?);
}
?
?
注:
1?tassArr[]數組里各事件處理函數的排列順序要與osalInitTasks()函數中調用各任務初
始化函數的順序保持一致
2?osalInitTasks()分配的id?.需要任務定義一個全局變量來保存
?
?
?
?
OSAL應用編程接口?
消息管理
任務同步
時間管理
中斷管理
任務管理
內存管理
電源管理
非易失性閃存管理
?
?
消處管理接口的定義在osal.h文件中可以看到,示例代碼如下:
/***?Message?Management?***/
/***??消息管理API?***/
??/*
???*?Task?Message?Allocation
???*?為消息分配緩存空間
???*/
??extern?uint8?*?osal_msg_allocate(uint16?len?);
?
??/*
???*?Task?Message?Deallocation
???*?為消息釋放緩存空間
???*/
??extern?uint8?osal_msg_deallocate(?uint8?*msg_ptr?);
?
??/*
???*?Send?a?Task?Message
???*?任務發送消息到消息隊列
???*/
??extern?uint8?osal_msg_send(?uint8?destination_task,?uint8?*msg_ptr?);
?
??/*
???*?Push?a?Task?Message?to?head?of?queue
???*?將任務消息壓入棧頂
???*/
??extern?uint8?osal_msg_push_front(?uint8?destination_task,?uint8?*msg_ptr?);
?
??/*
???*?Receive?a?Task?Message
???*?任務從消息隊列中讀取屬于自已的消息
???*/
??extern?uint8?*osal_msg_receive(?uint8?task_id?);
?
??/*
???*?Find?in?place?a?matching?Task?Message?/?Event.
???*/
??extern?osal_event_hdr_t?*osal_msg_find(uint8?task_id,?uint8?event);
?
??/*
???*?Enqueue?a?Task?Message
???*/
??extern?void?osal_msg_enqueue(?osal_msg_q_t?*q_ptr,?void?*msg_ptr?);
?
??/*
???*?Enqueue?a?Task?Message?Up?to?Max
???*/
??extern?uint8?osal_msg_enqueue_max(?osal_msg_q_t?*q_ptr,?void?*msg_ptr,?uint8?max?);
?
??/*
???*?Dequeue?a?Task?Message
???*/
??extern?void?*osal_msg_dequeue(?osal_msg_q_t?*q_ptr?);
?
??/*
???*?Push?a?Task?Message?to?head?of?queue
???*/
??extern?void?osal_msg_push(?osal_msg_q_t?*q_ptr,?void?*msg_ptr?);
?
??/*
???*?Extract?and?remove?a?Task?Message?from?queue
???*/
??extern?void?osal_msg_extract(?osal_msg_q_t?*q_ptr,?void?*msg_ptr,?void?*prev_ptr?);
?
?
任務同步管理接口?在文件OSAL.h中定義,示例代碼如下:
/***?Task?Synchronization??***/
?
??/*
???*?Set?a?Task?Event
???*?設置任務事件
???*/
??extern?uint8?osal_set_event(?uint8?task_id,?uint16?event_flag?);
?
?
??/*
???*?Clear?a?Task?Event
???*?清除任務事件
???*/
??extern?uint8?osal_clear_event(?uint8?task_id,?uint16?event_flag?);
?
?
?
時間管理接口?在文件OSAL_Timers.h中定義,示例代碼如下:
?/*
???*?Initialization?for?the?OSAL?Timer?System.
???*/
??extern?void?osalTimerInit(?void?);
?
??/*
???*?Set?a?Timer
???*?設置定時時間,到時后,相應事件被設置
???*/
??extern?uint8?osal_start_timerEx(?uint8?task_id,?uint16?event_id,?uint32?timeout_value?);
??
??/*
???*?Set?a?timer?that?reloads?itself.
???*/
??extern?uint8?osal_start_reload_timer(?uint8?taskID,?uint16?event_id,?uint32?timeout_value?);
?
??/*
???*?Stop?a?Timer
???*?停止定時器
???*/
??extern?uint8?osal_stop_timerEx(?uint8?task_id,?uint16?event_id?);
?
??/*
???*?Get?the?tick?count?of?a?Timer.
???*/
??extern?uint32?osal_get_timeoutEx(?uint8?task_id,?uint16?event_id?);
?
??/*
???*?Simulated?Timer?Interrupt?Service?Routine
???*/
?
??extern?void?osal_timer_ISR(?void?);
?
??/*
???*?Adjust?timer?tables
???*/
??extern?void?osal_adjust_timers(?void?);
?
??/*
???*?Update?timer?tables
???*/
??extern?void?osalTimerUpdate(?uint32?updateTime?);
?
??/*
???*?Count?active?timers
???*/
??extern?uint8?osal_timer_num_active(?void?);
?
??/*
???*?Set?the?hardware?timer?interrupts?for?sleep?mode.
???*?These?functions?should?only?be?called?in?OSAL_PwrMgr.c
???*/
??extern?void?osal_sleep_timers(?void?);
??extern?void?osal_unsleep_timers(?void?);
?
?/*
??*?Read?the?system?clock?-?returns?milliseconds
??*/
??extern?uint32?osal_GetSystemClock(?void?);
?
??/*
???*?Get?the?next?OSAL?timer?expiration.
???*?This?function?should?only?be?called?in?OSAL_PwrMgr.c
???*/
??extern?uint32?osal_next_timeout(?void?);
?
?
?
中斷管理接口?定義在soal.h文件中,示例代碼如下:
/***?Interrupt?Management??***/
?
??/*
???*?Register?Interrupt?Service?Routine?(ISR)
???*/
??extern?uint8?osal_isr_register(?uint8?interrupt_id,?void?(*isr_ptr)(?uint8*?)?);
?
??/*
???*?Enable?Interrupt
???*?開啟中斷
???*/
??extern?uint8?osal_int_enable(?uint8?interrupt_id?);
?
??/*
???*?Disable?Interrupt
???*?關閉中斷
???*/
??extern?uint8?osal_int_disable(?uint8?interrupt_id?);
?
?
任務管理接口?定義在soal.h文件中,
/***?Task?Management??***/
?
??/*
???*?Initialize?the?Task?System
???*?初始化osal,第一個被調用的函數
???*/
??extern?uint8?osal_init_system(?void?);
?
??/*
???*?System?Processing?Loop
???*/
#if?defined?(ZBIT)
??extern?__declspec(dllexport)??void?osal_start_system(?void?);
#else
??/*包含一個無限循環,查詢事件,執行處理函數,*/
??extern?void?osal_start_system(?void?);
#endif
?
??/*
???*?One?Pass?Throu?the?OSAL?Processing?Loop
???*/
??extern?void?osal_run_system(?void?);
?
??/*
???*?Get?the?active?task?ID
???*?取得任務id
???*/
??extern?uint8?osal_self(?void?);
?
?
內存管理接口,定義在OSAL_Memory.h文件中定義
/*
??*?Initialize?memory?manager.
??*/
??void?osal_mem_init(?void?);
?
?/*
??*?Setup?efficient?search?for?the?first?free?block?of?heap.
??*/
??void?osal_mem_kick(?void?);
?
?/*
??*?Allocate?a?block?of?memory.
??*/
#ifdef?DPRINTF_OSALHEAPTRACE
??void?*osal_mem_alloc_dbg(?uint16?size,?const?char?*fname,?unsigned?lnum?);
#define?osal_mem_alloc(_size?)?osal_mem_alloc_dbg(_size,?__FILE__,?__LINE__)
#else?/*?DPRINTF_OSALHEAPTRACE?*/
??/*分配指定大小的緩沖區*/
??void?*osal_mem_alloc(?uint16?size?);
#endif?/*?DPRINTF_OSALHEAPTRACE?*/
?
?/*
??*?Free?a?block?of?memory.
??*/
#ifdef?DPRINTF_OSALHEAPTRACE
??void?osal_mem_free_dbg(?void?*ptr,?const?char?*fname,?unsigned?lnum?);
#define?osal_mem_free(_ptr?)?osal_mem_free_dbg(_ptr,?__FILE__,?__LINE__)
#else?/*?DPRINTF_OSALHEAPTRACE?*/
??/*釋放分配的緩沖區*/
??void?osal_mem_free(?void?*ptr?);
#endif?/*?DPRINTF_OSALHEAPTRACE?*/
?
#if?(?OSALMEM_METRICS?)
?/*
??*?Return?the?maximum?number?of?blocks?ever?allocated?at?once.
??*/
??uint16?osal_heap_block_max(?void?);
?
?/*
??*?Return?the?current?number?of?blocks?now?allocated.
??*/
??uint16?osal_heap_block_cnt(?void?);
?
?/*
??*?Return?the?current?number?of?free?blocks.
??*/
??uint16?osal_heap_block_free(?void?);
?
?/*
??*?Return?the?current?number?of?bytes?allocated.
??*/
??uint16?osal_heap_mem_used(?void?);
#endif
?
#if?defined?(ZTOOL_P1)?||?defined?(ZTOOL_P2)
?/*
??*?Return?the?highest?number?of?bytes?ever?used?in?the?heap.
??*/
??uint16?osal_heap_high_water(?void?);
#endif
電源管理接口,定義在OSAL_PwrMgr.h文件中,示例代碼如下
??/*
???*?Initialize?the?power?management?system.
???*???This?function?is?called?from?OSAL.
???*
???*/
??extern?void?osal_pwrmgr_init(?void?);
?
??/*
???*?This?function?is?called?by?each?task?to?state?whether?or?not?this
???*?task?wants?to?conserve?power.?The?task?will?call?this?function?to
???*?vote?whether?it?wants?the?OSAL?to?conserve?power?or?it?wants?to
???*?hold?off?on?the?power?savings.?By?default,?when?a?task?is?created,
???*?its?own?power?state?is?set?to?conserve.?If?the?task?always?wants
???*?to?converse?power,?it?doesn't?need?to?call?this?function?at?all.
???*?It?is?important?for?the?task?that?changed?the?power?manager?task
???*?state?to?PWRMGR_HOLD?to?switch?back?to?PWRMGR_CONSERVE?when?the
???*?hold?period?ends.
???*/
??extern?uint8?osal_pwrmgr_task_state(?uint8?task_id,?uint8?state?);
?
??/*
???*?This?function?is?called?on?power-up,?whenever?the?device?characteristic
???*?change?(ex.?Battery?backed?coordinator).?This?function?works?with?the?timer
???*?to?set?HAL's?power?manager?sleep?state?when?power?saving?is?entered.
???*?This?function?should?be?called?form?HAL?initialization.?After?power?up
???*?initialization,?it?should?only?be?called?from?NWK?or?ZDO.
???*/
??extern?void?osal_pwrmgr_device(?uint8?pwrmgr_device?);
?
??/*
???*?This?function?is?called?from?the?main?OSAL?loop?when?there?are
???*?no?events?scheduled?and?shouldn't?be?called?from?anywhere?else.
???*/
??extern?void?osal_pwrmgr_powerconserve(?void?);
?
非易失性閃存管理接口?定義沒找到????????????
static?uint8??initNV(?void?);
?
static?void???setActivePage(?uint8?pg?);
static?void???setXferPage(void);
static?void???erasePage(?uint8?pg?);
static?void???cleanErasedPage(?uint8?pg?);
static?void???findOffset(?void?);
static?void???compactPage(?uint8?pg?);
?
static?void???writeWord(?uint8?pg,?uint16?offset,?uint8?*pBuf?);
static?void???writeWordM(?uint8?pg,?uint16?offset,?uint8?*pBuf,?osalSnvLen_t?cnt?);
總結
以上是生活随笔為你收集整理的Zigbee协议栈中OSAL的运行机理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zigbee中添加用户任务
- 下一篇: 回调函数之Java/C++版本