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的运行机理相关推荐

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

    OSAL的运行机理 事件表 函数表 使用查表法来取得事件所对应函数 taskCnt  任务总数 taskEvents 指向事件表首地址的指针 taskArr 事件处理函数数组,每一项都是一个函数指针 ...

  2. ZigBee协议栈之osal浅析

    ZigBee是目前比较流行的一种低功耗无线组网技术,主要用于智能家居控制以及智能工业生产.ZigBee大的特点就是低功耗.自组网. 说到ZigBee就不得不提IEEE802.15和ZigBee联盟,他 ...

  3. 二.了解zigbee协议栈中几个常用语句

    二.了解zigbee协议栈中几个常用语句 我在上一篇文章中说到过,zigbee作为一门通信技术,关键我们是要让它组起网来,虽然我们很多的实现还是用单片机的底板实现的:但要明白我们学习的核心在哪?在协议 ...

  4. CC2530下ZigBee协议栈中添加BH1750数字光照传感器

    项目里需要获得光照强度,之前用的是光敏电阻,但是光敏电阻实在不精确,换用BH1750数字光照传感器.网上购买后,送的资料都是单片机的,移植到ZigBee协议栈里面,时序有些问题,在网上找的一些资料,很 ...

  5. ZIGBEE通讯-10.ZigBee协议栈的无线点灯

    在ZIGBEE协议栈中已经自带了按键与LED的驱动与使用函数,所以只需要将按键与LED修改为使用的开发板所连接IO就可以使用了.接下来将主要分析在协议栈中按键的初始化.按键的检测以及按键事件的传递与处 ...

  6. Zigbee协议栈单播收发字符字符串

    Z-stack协议栈简单知识: IEEE 802.15.4 定义了 PHY(物理层)和 MAC(介质访问层)技术规范:ZigBee 联盟定义了 NWK(网络层).APS(应用程序支持子层).APL(应 ...

  7. 蓝牙协议栈中的 OSAL

    蓝牙协议栈里的操作系统叫做 OSAL(操作系统抽象层).它并非一个真正意义上的操作系统,它只是实现了操作系统的一些功能,如任务切换.内存管理. OSAL 产生的根源:基于蓝牙协议栈开发的产品,实际上是 ...

  8. zigbee协议栈OSAL分析

    本文从源程序出发,分享本人学习zigbee协议栈的一些理解,介绍zigbee协议栈OSAL任务调度及用户自定义任务的调度处理过程.为了便于抓住本质,理清思路,本文剔除一些无关部分. 程序的入口是ZMa ...

  9. 蓝牙BLE(协议栈、OSAL、蓝牙APP工具)

    目录 蓝牙配对和绑定 蓝牙4.0 BLE 信道(RF Channel) BLE协议栈分层 PHY层(Physical layer 物理层) LL层(Link Layer 链路层) HCI层(Host ...

最新文章

  1. 【yolo目标检测】(1) yolov3,网络结构Darknet53,特征提取
  2. 【救援过程】升级openssl导致libcrypto.so.1.1动态库不可用
  3. 第十六届智能车竞赛参赛队伍提问-2021-6-15
  4. javaweb火车车次信息管理+文件_厦门火车站启动“双十一”电商黄金周运输 投入列车数量为历年新高...
  5. 激发你的灵感:16个精美视差效果网页设计作品
  6. 小程序弹出层禁止列表滑动_是时候展现真正的技术了!小程序教程来了——百战Web前端课程更新05.07...
  7. java web 分页技术_javaweb分页的后端实现
  8. Linux下Weblogic创建域方法和步骤
  9. 哪种存储器是非易失的_非易失性存储器和易失性存储器有什么全部详细资料对比...
  10. scratch编程记忆力小游戏
  11. SQL语句:联合查询
  12. USB-SC-09(假冒PL2303HXA芯片)WIN7-64位驱动之终极大法
  13. oracle diagnosticdest,Oracle 11g自动诊断信息库(Automatic Diagnostic Repository,ADR)概述
  14. 如何有效的快速提高自己的编程能力
  15. python打印各种三角形_如何使用Python 打印各种三角形
  16. python使用代理爬虫_python使用代理爬虫导致无法访问网页
  17. 万字干货:当了5次韭菜总结出来的抖音运营指南
  18. 【密码学】1.1密码学发展史
  19. python初学-下载模块后导入失败(windows)
  20. 企业品牌之电子杂志营销解决方案

热门文章

  1. 从0搭建在线聊天室,只需4步!
  2. 网易云信集成视频教程(四):如何快速实现iOS登录登出?
  3. PaaS服务之路漫谈(一)
  4. Linux-shell
  5. 2019年4月8日 1021. Remove Outermost Parentheses
  6. 体验一键php/java环境安装工具oneinstack
  7. unix基础之改变文件权限
  8. Access 的top和order by 的问题
  9. java mysql开发_Java数据库开发
  10. Windows下cmd常用命令【5分钟掌握】