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()”接口,否则一直循环定时操作。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql跨节点join——federated引擎

一、 什么是federated引擎 mysql中的federated类似于oracle中的dblink。 federated是一个专门针对远程数据库的实现,一般情况下在本地数据库中建表会在数据库目录中生成相对应的表定义文件,并同时生成相对应的数据文件。 [图] 但是通过federated引擎创建…

【阅读SpringMVC源码】手把手带你debug验证SpringMVC执行流程

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 ✿ 阅读源码思路: 先跳过非重点,深入每个方法,进入的时候可以把整个可以理一下方法的执…

Zabbix监控(十六):分布式监控-Zabbix Proxy

说明:Zabbix支持分布式监控,利用Proxy代理功能,在其他网络环境中部署代理服务器,将监控数据汇总到Zabbix主服务器,实现多网络的分布式监控,集中监控。1、分布式监控原理Zabbix proxy和Zabbix server一样&am…

CC254x--BLE

BLE协议栈 BLE体系结构,着重了解GAP和GATT。 PHY物理层在2.4GHz的ISM频段中跳频识别。LL连接层:控制设备的状态。设备可能有5中状态:就绪standby,广播advertising,搜索scanning,初始化initiating和连接con…

Azure Container App(一)应用介绍

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 一,引言 容器技术正日益成为打包、部署应用程序的第一选择。Azure 提供了许多使用容器的选项。例如&#xff0…

怎样配置键盘最方便,以及一些设计的思考

使用Emacs的人,如果肯折腾,肯定有重新映射键盘的经历。我原来经常看到的是把Ctrl和Capslock交换,但是我感觉没什么道理,因为Ctrl已经用的很熟练了,换了反而不方便,而且对其他程序影响太大。那么我们就要使用…

profile、服务、特征、属性之间的关系

一个profile有很多的服务,一个服务又有很多的特性,一个特性中又有几种属性条目组成。 profile(数据配置文件) 一个profile文件可以包含一个或者多个服务,一个profile文件包含需要的服务的信息或者为对等设备如何交互的…

机器学习实战 | SKLearn最全应用指南

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 作者:韩信子ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/41 本文地址:http…

Scheme语言入门

2019独角兽企业重金招聘Python工程师标准>>> Scheme语言入门 最早听说 LISP,是 Stallman 的 GNU Emacs 中将 LISP 作为嵌入语言,定制和增强 Emacs。GNU Emacs 是一个文本编辑器,文本就是一种符号,而 Lisp 正好就是针对…

如何将docker 镜像上传到docker hub仓库

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 如何将docker 镜像上传到docker hub仓库 目录* 如何将docker 镜像上传到docker hub仓库 背景 1.注册docker hub账号 2.…

ThinkPHP框架 _ 学习3

【路由解析】 通过url地址get参数找到指定的控制器,并进行对应方法调用请求 http://网址/index.php?m模块名称&c控制器&a方法 以上url地址信息代码不够优雅、不安全。 tp框架url地址可以由以下四种 http://网址/index.php?mXX&cXX&aXX 基本get模…

The slave I/O thread stops(equal MySQL server ids)

在学习replication时遇到了如下问题:显然看到Slave_IO_Running 为NO 表示有问题;到日志里查看,错误如下:position 98100121 17:09:03 [ERROR] The slave I/O thread stops because master and slave have equal MySQL server ids;…

pytest配置文件pytest.ini

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 说明: pytest.ini是pytest的全局配置文件,一般放在项目的根目录下是一个固定的文件-pytest.ini可以…

基于积分墙盈利模式的APP架构思考

基于积分墙盈利模式的APP架构思考from: http://kuailiyu.cyzone.cn/article/4156.html个人感言:一款小游戏好不容易辛辛苦苦开发出来,但是在后期如何不注重推荐,其下场可想而知。而个人游戏开发者的产品很难实现应用内付费集成,技…

【死磕NIO】— 探索 SocketChannel 的核心原理

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 大家好,我是大明哥,一个专注于【死磕 Java】系列创作的程序员。 【死磕 Java 】系列为作者「chenssy…

session的存储方式

1、保存在IIS进程中 2、保存在StateServer上 3、保存在SQL Server数据库中 转载于:https://www.cnblogs.com/dashi/archive/2012/10/10/4034799.html

PixiJS - 基于 WebGL 的超快 HTML5 2D 渲染引擎

Pixi.js 是一个开源的HTML5 2D 渲染引擎,使用 WebGL 实现,不支持的浏览器会自动降低到 Canvas 实现。PixiJS 的目标是提供一个快速且轻量级的2D库,并能兼容所有设备。此外,让开发者无需了解WebGL,就可以感受到硬件加速…

腾讯的老照片修复算法,我把它搬到网上,随便玩

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 大家好,之前向大家介绍并跑通了腾讯开源的老照片修复算法(AI 黑科技,老照片修复&#xf…

java的事务类型及定义

转载:什么是事务:首先,说说什么事务。我认为事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行&#x…