CC254x--OSAL
OSAL运行原理
蓝牙协议栈PROFILE、所有的应用程序、驱动等都是围绕着OSAL组织运行的。OSAL(Operating System Abstraction Layer)操作系统抽象层,它不是一个真正的操作系统(它没有 Context Switch 上下文切换功能),但它巧妙地组织各任务,支持任务优先级,任务之间可以通过事件和消息来通信,为任务提供软定时器和动态内存分配。要避免的陷阱是,应用任务的单个函数运行时间不能太长 (如操作大批量数据的 Flash 写),否则它无法及时调度高优先级的 LL(Link Layer)任务而导致蓝牙通信中断。
OSAL 为每一个任务函数分配了一个 16 位的EVENT 事件,每一位代表一个事件,其中最高位代表的事件为 SYS_EVENT_MSG,这个事件被 OSAL 系统保留,其他的 15 位可以由用户定义,OSAL 在主循环里运行每次都会检查每个任务函数的是否有事件发生(事件置位),如果有事件发生,将通过 taskid 来调用发生事件的任务函数,并将发生的事件传递到该函数中去,由任务函数处理对应的事件。
为什么要将返回值设置到tasksEvents中,就是因为其本质是一个单任务循环,如果某个子任务时间执行过长,会影响更高优先级的任务的响应变慢,影响整体性能。因此如果一个任务执行比较长,宜进行分割,在返回值那里设置继续处理事件,然后返回大循环,看看有没有更高优先级的任务需要执行。
事件和任务对应关系
事件和任务的事件处理函数是如何关联起来的呢?
建立一个事件表,保存各个任务对应的事件。【uint16 *tasksEvents;】。tasksEvents为指向一个内存分配的事件数组的指针。比如:tasksEvents[0]为第0个任务的事件变量(short int)。
建立另一个函数表,保存各个任务事件处理函数的地址。【const pTaskEventHandlerFn tasksArr[] =】将会根据tasksArr[x]去执行对应的回调函数。
然后将这两张表建立某种对应关系,【void osalInitTasks( void ),初始化task_id和tasksArr[]的函数指针对应关系】【uint8 osal_set_event( uint8 task_id, uint16 event_flag ),设置事件发生】,蓝牙协议栈也会调用并设置任务,具体的实现已经被封装起来了。
当某一事件发生时则查找函数表找到对应的事件处理函数即可。【events = (tasksArr[idx])( idx, events );,调用idx变好的函数指针回调函数】
//定义了一个函数指针
/** Event handler function prototype*/
typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );//这是一个数组,该数组的每一项都是一个函数指针,指向了事件处理函数
// The order in this table must be identical to the task initialization calls below in osalInitTask.
const pTaskEventHandlerFn tasksArr[] =
{LL_ProcessEvent, // task 0Hal_ProcessEvent, // task 1HCI_ProcessEvent, // task 2
#if defined ( OSAL_CBTIMER_NUM_TASKS )OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), // task 3
#endifL2CAP_ProcessEvent, // task 4GAP_ProcessEvent, // task 5GATT_ProcessEvent, // task 6SM_ProcessEvent, // task 7GAPRole_ProcessEvent, // task 8GAPBondMgr_ProcessEvent, // task 9GATTServApp_ProcessEvent, // task 10SimpleBLEPeripheral_ProcessEvent // task 11
};//该变量保存了任务的总个数
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );//这是一个指针,指向了事件表的首地址,事件表实际上是一个内存分配的数组
uint16 *tasksEvents;
OSAL是一种事件驱动的轮询式操作系统。事件驱动是指发生事件后采取相应的事件处理方法,轮询指的是不断地查询是否有事件发生。
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
在系统初始化时,将所有任务的事件初始化为0。通过taskEvents[idx]是否为0来判断是否有事件发生【if (tasksEvents[idx])】。如果有事件发生,则查找函数对应的事件处理函数对事件进行处理【events = (tasksArr[idx])( idx, events );】。
事件表使用数组来实现,数组的每一项对应任务的事件,每一位表示一个事件;函数表使用函数指针数据来实现,数组的每一项是一个函数指针,指向了事件处理函数。
OSAL提供的API
总体而言,大致可以分为10个方面:
1.消息管理
2.任务同步
3.时间管理
4.中断管理
5.任务管理
6.内存管理
7.电源管理
8.非易失性闪存管理
9.时钟管理10.其他常用
事件
OSAL为每个任务函数分配了一个16位的事件变量,每一位代表一个事件。最高位0x8000保留为系统事件SYS_ENENT_MSG。其余的15位留给用户自定义需要的事件。通常事件由定时器启动,比如2s后我要点亮LED1,这就需要发送一个点亮LED1的事件,然后等待,当2s后接收到点亮LED1事件的时候调用HAL层开关LED1的函数开启LED1。
消息
MAG是比EVENT事件更具体并且可以携带数据的一种通信方式。而且MSG的标记是按数值,而不是按位。比如0x02和0x03是两个不同的消息,但是对于事件0x03则是0x01和0x02事件的组合。MSG收发使用osal_mag_send()和osal_msg_receive();当调用osal_msg_send()发送一个MSG的同时会在EVENT列表中触发一个message ready event。为了降低消息传递的开支,通常传递指向消息的指针。
消息与事件的区别
讲解消息队列之前需要讲解一下消息与事件的区别。
事件是驱动任务去执行某些操作的条件,当系统中产生了一个事件,OSAL 将这个事件传递给相应的任务后,任务才能执行一个相应的操作(调用事件处理函数去处理)。
通常某些事件发生时,又伴随着一些附加信息的产生,例如:主机 GATT 接收到数据后,会产生 GATT_MSG_EVENT 消息,但是任务的事件处理函数在处理这个事件的时候,还需要得到所收到的数据。
因此,这就需要将事件和数据封装成一个消息,将消息发送到消息队列osal_msg_send,然后在事件处理函数中就可以使用 osal_msg_receive 从消息队列中得到该消息。这里需要说明一点,消息一般用于不同任务函数之间的数据传递,因为不同的任务具有各自的堆栈空间。在同一任务中使用全局函数或者用户事件完全能够胜任。当然消息也可以在同一个任务中传递数据。
EVENT用于同一任务函数传递命令,而MSG则用于不同的任务函数传递命令数据。
这里需要说明一点,消息一般用于不同任务函数之间的数据传递,因为不同的任务具有各自的堆栈空间。在同一任务中使用全局函数或者用户事件完全能够胜任。当然消息也可以在同一个任务中传递数据。
事件处理
消息处理
OSAL 维护了一个消息队列,每一个消息都会被放到这个消息队列中去,当任务接收到事件后,可以从消息队列中获取属于自己的消息,然后调用消息处理函数进行相应的处理即可。
Osal_msg_allocate()为消息分配缓存空间,分配之后,可以填充消息,然后通过osal_msg_send( ) 将消息发送出去,然后任务函数中通过 osal_msg_reveive()函数接收属于 自己的消息,并处理,最后调用osal_msg_deallocate() 函数销毁由Osal_msg_allocate()分配的内存空间。
下面是按键的消息处理过程,按键的消息最终将会发送到第一次注册的任务中去。
这里需要说明一点,消息一般用于不同任务函数之间的数据传递,因为不同的任务具有各自的堆栈空间。在同一任务中使用全局函数或者用户事件完全能够胜任。当然消息也可以在同一个任务中传递数据。
事实上,它只是发了一个KEY_CHANGE事件,而键值是以MSG消息的形式发到系统的消息队列,而该消息也会带上目标taskId的标识。
如下代码可以从消息队列中得到一个消息:pMsg = osal_msg_receive( registeredKeysTaskID))
时间管理
时间管理API用于开启和关闭定时器,定时时间一般为毫秒级定时。
osal_start_reload_timer()和osal_start_timerEx()功能一样,但是本接口还多了一个功能:就是定时时间到后相应事件被执行,并重新加载定时器,也就是又重新设置了定时器,继续进行定时工作,除非调“osal_stop_timerEx()”接口,否则一直循环定时操作。
CC254x--OSAL相关推荐
- CC2540/CC2541/CC254x之OSAL操作系统抽象层
测试环境 协议栈版本:BLE-CC254x-1.4.0 开发环境IAR版本:IAR 8.20 硬件设备:CC2540/CC2541开发板 示例测试Demo工程:simpleBLEPeripheral工 ...
- CC254x到CC2640
介绍 TI-RTOS是CC26xx设备上蓝牙低功耗项目的新操作环境.该软件是一个多线程环境,其中,协议栈.应用程序及其配置文件存在于不同的线程上.TI-RTOS具有与OSAL相似的功能,但实现它们的机 ...
- TI CC254x BLE教程 4
TI的CC254x芯片 1. SoC 2. RF收发器+8051MCU 128/256KB Code空间. 3. Master或者Slave 4. 可编程flash 5. 8KB SRAM 6. 全软 ...
- CC2540 OSAL 学习其中原理,以及 给任务 添加 一个事件(定时发送串口消息)
参考学习大神博客: http://blog.csdn.net/feilusia/article/details/51083953 : http://blog.csdn.net/xiaoleiacmer ...
- 5、CC2541芯片中级教程-OSAL操作系统(PWM+看门狗)
本文根据一周CC2541笔记汇总得来-- 适合概览和知识快速索引-- 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...
- Zigbee协议栈中OSAL的运行机理
OSAL的运行机理 事件表 函数表 使用查表法来取得事件所对应函数 taskCnt 任务总数 taskEvents 指向事件表首地址的指针 taskArr 事件处理函数数组,每一项都是一个函数指针 ...
- 蓝牙BLE(协议栈、OSAL、蓝牙APP工具)
目录 蓝牙配对和绑定 蓝牙4.0 BLE 信道(RF Channel) BLE协议栈分层 PHY层(Physical layer 物理层) LL层(Link Layer 链路层) HCI层(Host ...
- IAR平台移植TI OSAL到STC8A8K64S4A12单片机中
玩过TI 的ZigBee或者BLE的人,都会接触到OSAL.OSAL是什么?OSAL英文全称:operating system abstraction layer(操作系统抽象层).基于OSAL的调度 ...
- 蓝牙协议栈中的 OSAL
蓝牙协议栈里的操作系统叫做 OSAL(操作系统抽象层).它并非一个真正意义上的操作系统,它只是实现了操作系统的一些功能,如任务切换.内存管理. OSAL 产生的根源:基于蓝牙协议栈开发的产品,实际上是 ...
- BLE协议栈学习2——OSAL
OSAL简介 BLE 协议栈包含了 BLE 协议所规定的基本功能,这些功能是以函数的形式实现的,为了便于管理 这些函数集,BLE 协议栈内加入了实时操作系统(并非真正意义上的操作系统),称为 OSAL ...
最新文章
- VTK:参数化超环形用法实战
- FFmpeg 硬件加速方案概览 (上)
- Java 8中最快的垃圾收集器是什么?
- CAReplicatorLayer复制Layer和动画, 实现神奇的效果
- html怎么实现单个li效果,基于DIV+ul+li实现的表格(多示例)
- 站点简介(欢迎大家踊跃参与本站站点的建设,谢谢)
- pyecharts折线图坐标轴范围设置_多层折线图,一对一展现数据趋势,图表就应如此美丽...
- Java知多少(51)finally
- VTK点云数据如何导入MeshLab
- 电信天翼网关路由器的超级密码
- 二元二次方程例题_二元二次方程组 解法 例题精编版
- phython学习笔记1
- 产品经理干久了,有哪些后遗症?
- shell 判断字符串长度
- 拍照基础方法及构图技巧
- Jmeter基础系列4-创建一个HTTP请求实例
- 客户贷后还款提醒优化项目
- 愿编程不再乱码(含Qt)-根因深究
- 充电池中热敏电阻作用
- 研究型论文_用于优化入侵检测类不平衡数据集中SMOTE比率的机器学习方法(英文论文)
热门文章
- Fix an “Unapproved Caller” SecurityAgent Message in Mac OS X
- Android处理ListView中的Item中的Button按钮不能点击的问题
- 2、Eternal框架-svn_有更新!
- 医疗大数据处理流程_我们需要数据来大规模改善医疗流程
- flink 检查点_Flink检查点和恢复
- 城市轨道交通运营票务管理论文_城市轨道交通运营管理专业就业前景怎么样?中职优选告诉你...
- 敏捷数据科学pdf_敏捷数据科学数据科学可以并且应该是敏捷的
- 渐进式web应用程序_渐进式Web应用程序与加速的移动页面:有什么区别,哪种最适合您?
- QueryList 配置curl参数 的文档位置 QueryList抓取https 终于找到了
- 基于相关性分析系统性能瓶颈