logo资料库

OSAL开发指南.pdf

第1页 / 共11页
第2页 / 共11页
第3页 / 共11页
第4页 / 共11页
第5页 / 共11页
第6页 / 共11页
第7页 / 共11页
第8页 / 共11页
资料共11页,剩余部分请下载后查看
ghostyu.taobao.com OSAL 编程指南 Ghostyu 2013-03-06 1
ghostyu.taobao.com 版本 V1.0 2013-03 初始版发布 2
ghostyu.taobao.com 目的 本文在 BLE 入门指南的基础上进一步阐述 OSAL 的机制和编程方法,希望对 BLE 初学者所有帮助。 OSAL 的具体实现方法不再本文讨论范围,请参见后续文档。 OSAL 层的 API 使用方法,请参数《OSAP API 用户手册》 一、几个小问题。 1、OSAL 是什么 操作系统抽象层,可以理解为运行在 CC2540 上的操作系统,并且把协议栈的代码、硬件处理的代码, 用户程序的代码等分别放到了 OSAL 层的不同任务函数中去,各任务函数通过消息、事件的方式来通信。 2、什么是 EVENT 事件 OSAL 为每个任务函数分配了一个 16 位的事件变量,每一位代表一个时间,最高位 0x8000 保留为系统 事件 SYS_EVENT_MSG。其余的 15 位留给用户自定义需要的事件。通常事件由定时器启动,比如两秒后我要 点亮 LED1,这就需要发送一个点亮 LED1 的事件,然后等待,当 2 秒后接收到点亮 LED1 事件的时候调用 hal 层开关 LED1 的函数开启 LED1. 3、什么是 MSG 消息 MSG 是比 EVENT 事件更具体并且可以携带数据的一种通信方式。而且 MSG 的标记是按数值,而不是按位。 比如 0x02 和 0x03 是两个不同的消息,但对于事件 0x03 则是 0x01 事件和 0x02 事件的组合。MSG 收发使用 osal_msg_send()和 osal_msg_receive();当调用 osal_msg_send()发送一个 msg 的同事会在 EVENT 列表中 触发一个 message ready event。 3
ghostyu.taobao.com 二、OSAL 的组成。 OSAL 层的源码如下图,这五个文件的分别的作用为 OSAL.c 内存数据复制、比较等函数和 msg 消息的发送接收等函数的实现。 OSAL_Clock.c 系统滴答时钟 OSAL_Memory.c 系统“动态内存”管理,这里是打了引号的动态内存管理,其实是分配的一块静态内存池,然后通过标记 的方式来动态的管理该静态内存,这样即无需复杂的动态内存实现技术又有效的利用了单片机有限的内存 空间。实现的功能相当于 PC 上的 malloc 函数。 OSAL_PwrMgr.c 功率管理 OSAL_Timers.c 系统定时器管理,任务函数的中事件定时器 osal_start_timerEx()就来自该源文件。该源文件维护了一个 定时器队列,每当用户调用 osal_start_timerEx(),就会再该队列上添加一个成员,当定时事件到时,通 知上层,并删除相应的成员。 三、OSAL 使用范例分析 在这一节,我们分析来分析应用程序使用 OSAL 层的两种最常见的范例分析,将它的来龙去脉展现给用 户。 以 SimpleBLEPeripheral 为例,一种是用户事件的启动和接收,第二种是消息的发送和接收。 3.1 用户事件的启动和接收 在 Z-Stack 协议栈的用户程序中,为了实现特定的功能,除了使用系统事件外,用户自定义一些用户 事件是非常有必要的。比如要周期性的去检测某个 GPIO 的状态,或者每隔一段时间发送一个命令等,都需 要自定义事件来完成。 在 SimpleBLEPeripheral 中,常见的用户事件 每个任务函数都类似这样的格式: 4
ghostyu.taobao.com 每一个 if 语句均对应一个 EVENT 事件。首先处理的是 SYS_EVENT_MSG 系统消息事件。其次是用户自定 的事件,注意,每个任务函数每次只处理一个事件(注意每个 if 中的 return),也就是说本次处理完了 SYS_EVENT_MSG 事件会直接 return。然后准备下一次 OSAL 层任务调度到该任务时再处理用户自定义的 SBP_START_DEVICE_EVT,如果此时正好又发生了一个 SYS_EVENT_MSG 系统消息事件,那么将继续先处理 SYS_EVENT_MSG,直到空闲的时候才会去处理任务自定义的事件。 留心的读者应该发现了一个问题,这个 if 框架是处理事件的,也就是说事件已经发了才会来处理,那 么事件是在哪发起的呢? 我们先寻找 SBP_START_DEVICE_EVT 事件的启动。 在 SimpleBLEPeripheral_Init 任务初始化函数结尾处启动了该事件。 … osal_set_event()函数是事件启动函数,参数 1 是需要启动定时器的任务 ID,第二个参数是启动的事件 ID, 调用改函数后会立刻出发启动的事件,接着在该任务函数中就会接收到 SBP_START_DEVICE_EVT 事件,进而 进入下列代码中执行: 5
ghostyu.taobao.com 对该事件作出何种相应,完全由用户决定。注意,定时器定时均为一次性的,不会自动装载。 至于 osal_set_event 和 osal_start_timerEx 函数具体做了什么,我们将在后续的文档开发资料用详 细的阐述,本文档只为 OSAL 编程做指导。OSAL 实现的细节不在讨论范围内。 3.2 MSG 消息的发送与接收 在 SimpleBLEPeripheral 任务初始化函数中有这样一条代码: 这个函数来自 OnBoard.c 源文件中 向一个全局变量中赋值自己的任务 ID,从代码中可以看出,只能第一个调用改函数的任务才能成功注 册到按键服务。那这个全局变量在何时使用呢? 我们暂且放下该问题,在 main.c 初始化过程有如下代码: 该函数的实现如下: 6
ghostyu.taobao.com 该函数通过 HalKeyConfig 接口注册了一个按键回调函数 OnBoard_KeyCallback,首先看 HalKeyConfig 函数的实现: 将上述的回调函数的地址复制给了了函数指针变量。通过跟踪发现该函数指针变量在按键的轮询函数 中调用,如下图: 7
ghostyu.taobao.com 回调函数的一个非常的做用是可以隔离每一层,而且还有一点点面向对象的开发方式,在这里底层的 按键查询函数调用一个函数指针,而非具体的函数,这样就将处理按键的接口留给了上层,上层应用中, 只需解析函数指针传入的参数 1:keys 就知道是哪个按键被按下了。 我们再回到刚才的 OnBoard_KeyCallback 回调函数处,该回调函数代码如下: 该函数又将按键值向下传递到 OnBoard_SendKeys()函数里,通过名字应该能够看出来,应该是发送了 按键消息。果然是调用了 osal_msg_send 发送了一个消息,并且在消息中附加了消息事件名称 KEY_CHANGE, 按键值,和状态,按键的处理权又向下传递,最后发送到谁第一次注册按键服务端任务函数中去。 8
分享到:
收藏