理解 Tasks,Timers,Schedulers
在一个蓝牙系统中,有很多工作需要维护,连接管理的消息需要处理,输入数据必须处理
输出的数据必需发送到基带管理器上,如果要通过主机控制器与主机交互还必须编址等,
所以处理器要分出不同的时间来处理不同的任务(即多线程)。
每一个任务有他自己的调用堆栈,自己的 IO 队列,都可以从处理器得到回应。有一个任务
用来协调其他任务,叫做核心任务(kenel),也被看成调度( Schedulers)。 BlueCore
系统采取轮询的运行方式,处理器轮流运行任务(而非抢占式)。
当任务阻塞时,调度停止运行该任务(当一个任务调用一个用于等待事件发生的系统调用
时,任务将进入阻塞状态)。所以当一个任务永远不被阻塞时,其他的任务将永远不会有
机会运行。
遇到上面的情况,如果你的应用程序不能够被阻塞,就需要关掉整个蓝牙功能,但是在蓝
牙 堆 栈 里有 很多 实 时 性的 操作 要 求 运 行 , 所 以 不 能 够 这样 做 。 为 了 解决 这 个 问 题 ,
BlueCore 提供了一种环境叫做 VM,来保护堆栈的正常运行,而不会受到占用大量时间的
应用程序的影响。调度并不是直接调用应用程序,而是调用虚拟机,然后通过虚拟机解释
器的解释,虚拟机可以执行很多操作。这样应用代码如果是一个无限循环虚拟机仍旧可以
运行应用程序中预置的指令,所以无限循环不会无限运行下去。
虚拟机调度
片上的调度器在给其他待处理过程分配处理时间之前仅允许处理有限的虚拟机命令。这意
味着不能够指望运行在虚拟机上的应用程序能快速的作出反应。
一个无限的 while 循环会阻止芯片进入休眠状态而增加功耗。而且虚拟机并不会一直运行
该循环,而是会在运行一段时间以后转而去处理蓝牙协议栈和应用程序的其他任务。(虚拟
机调度是由 scheduler 实现的,调度程序的代码可见,虚拟机则只提供了接口函数)
for(;;)
{
uint16 del = sched1() ;//有事件发生处理事件,没有事件发生返回
VmWait(del) ;//应用程序运行在虚拟机上,调用此函数时,虚拟机进入
等待状态,上面运行的所用程序都将被阻塞
//从而使蓝牙堆栈上的实时性较强的操作的以进行,而不受应用程序的
影响
}
使用 bluelab 库
Bluelab 提供了各种库,库里提供了支持 basic C 的函数。当连接时,所有目标文件都会被
用到,而且缺少的符号将从库中导入。每一个符号都是从最开始的库(按照命令指定的顺
序)获得的。也就是说应用程序的 makefile 必需位于库前重写。
Scheduler 依赖于 message 和 timer 库。一些应用程序要求 scheduler,但是并不一定这两个库
东需要。这种情况可以用这两个库的简化版来代替,将会占用更少的代码和数据空间。
应用程序框架、连接管理器、调度器、Timer、BlueStack、I2C、消息库和服务发现库需要
被解释执行,而剩余的库将按原有模式运行,不必经过 VM 的解释器。
库分为三种:
1) 基本库。提供支持运行和调试 C 代码的功能。
2) CSR 库。
3) 应用程序库。提供对运行在 BlueCore 上的应用程序的支持。这些库的源代码在 src/lib
中。可以通过在当前目录下输入 make install 命令来重建和安装。这就可以使库代码的
调试可以像应用程序代码调试那样进行源码级的调试。