system: [SYSTEM]

user: 2. CAN总线的调度算法分析 CAN总线利用数据帧中的标识符表示信息的来源和优先级。标识符既可以静态设定，也可以动态设定，即利用标识符可以实现静态或者动态的信息优先级。在满足可调度性的实时调度算法中，目前常用的是优先级驱动的实时调度算法，它可分为静态优先级调度算法和动态优先级调度算法 [ 1 ] 。 以上两种调度算法是分别是基于主从式的，和分布式的。基于主从式的调度算法是基于主从式数据结构，利用分时调度原理来避免节点数据的冲突。而基于分布式的调度算法则是在网络分布式结构的基础上，处于CAN总线上的各个节点根据传输的需要自行改变自己的报文优先级，从而达到网络实时性的需求。 2.1. 基于TTCAN技术的时间触发调度算法 时间触发TTCAN总线调度算法充分利用了TDMA的时分复用技术，时间触发CAN总线上的每个节点都占有一个时隙，节点在时隙内拥有总线的使用权 [ 2 ] 。 每个节点在总线周期内至少有一个时隙。这样每个总线周期内，每个节点都有访问总线的机会。从而不会造成优先级低的节点因为多次竞争失败而不能发送数据。 TTCAN由时间进程驱动，其时间触发调度由顺序固定的时间窗组成。时间窗是用于交换报文的时间片断，通常有三类时间窗：专用时间窗(特定的周期性报文)、仲裁时间窗(通过仲裁访问总线的报文)和空闲时间窗(为总线扩展所保留)。专用时间窗类似于TDMA(时分多路访问)，属于离线进行的静态调度，所有流程和时间参数均需要预先指定，并可以在多级或多个TTCAN网络内实现同步 [ 3 ] 。TTCAN的全局时间由时间主机周期发送的参考报文产生，它的总线最多可以配置8个具有优先级的时间主机节点，以确保总线的连续、确定性通信，优先级最高的时间主机为当前时间主机。总体来说TTCAN的总线调度过程如下图1所示。 2.2. 基于分布式的动态优先级调度 由于传统的物理层和数据链路层CAN2.0B协议已经不能满足复杂条件下，总线实时性的需求，所以我们为了让处于总线上的节点有效的收发数据，需要在应用层实现调度算法。而CAN总线中以数据帧为例如下图2，将仲裁场的标识符分为优先级块和识别块二部分 [ 4 ] 。优先级部分已经不再具有协议帧的标识功能，而只是表示协议帧的优先级功能，它可以根据实际情况被系统调整。 由于11位CAN ID标识的ID数量有限，所以以29位CAN ID为例进行说明。 如表1所示，优先级块和识别块的位数分别是n、m。用集合表示为A n 、B m ，那么A n 和B m 中的元素个数分别是2 n 和2 m 。n = m的情况下，所有的识别块都有对应的优先级，但总的标识符为29位奇数个数，所以必须n < m，取v = n，集合Cv∈Bm。所以对于系统来说未使用的报文数量应该为2 m − 2 v 。 图1. TTCAN总线调度流程图 图2. CAN扩展帧结构图 Table 1 29 bit CAN ID identifier partitio 名称 优先级块 识别块 bit n m 表1. 29位CAN ID标识符划分 处于CAN总线上的节点向总线发送报文时，所有的待发送报文被放在一个队列Q内，假设单帧报文的发送时间为t F (包括报文准备发送时间和报文在总线的传输时间以及等待传输完成时间)，当前报文在队列中的位置为P。 (1) 对于总数为2 n −1的报文，假设对应每个ID的报文在队列Q中的个数为D d ，那么任一报文所需要发送至总线需要的等待时间为： T w = t f × ∑ d = 1 P − 1 D d (2) 公式(2)是固定优先级调度模式下，队列Q中报文的等待时间，可以看出队列中当前报文之前报文的数量越多，所等待的时间就越长。队列Q尾报文发送所等待的时间最长，大约为： T w = t f × ∑ d = 1 2 n − 2 D d (3) 可以看出n和D d 越大，队列Q中的报文越多，队尾报文的等待发送时间就越长，在网络拥堵的情况下，系统的实时性和可靠性将大幅度下降。 为了保障系统的可靠性和实时性，提高报文的传输效率，就必须有效控制报文的等待时间T。除了优化系统的效率以及网络的传输效率外，可以调节的参数就是报文在队列Q中的位置P。位置P是报文在队列中的优先级，这里引入动态优先级调度通过不断改变队列的位置P来实现报文的实时传输。 η = { D d } P = 2 n − 1 − f ( t λ ， t f ， η ) (4) 函数 包含了当前报文的最长响应时间 t λ ，每帧报文的传输时间 t f ，以及队列Q中报文的个数集合 η 。 初始条件下，每个节点的优先级各不相同。在没有发生冲突的情况下，各个节点按初始固定优先级(优先级块的集合为A n )完成数据的发送。 当发生冲突后，总线对节点的发送进行仲裁，优先级高的节点在竞争中胜出发送数据。为了保证当前报文传输的可靠性，为了能让竞争失败的节点在下次的竞争中有更大的概率胜出，可以把竞争失败节点的优先级提高一个等级来参加下一次的竞争。 优先级晋升的原则是保证当前节点的最长响应时间大于其在队列Q中的等待时间t w (即t λ > t w )只有这样该报文才会及时发送至总线，保证时效。 最坏的情况，网络最大的负荷情况下，CAN总线下所有的节点处于一种拥堵的状态，这时候的优先级调度的算法如下： ① 已知总线上各报文的最长响应时间，找出响应时间最小的报文P 1 ，其最长响应时间为t 1 ，此时t 1 = min{t λ }，t λ ∈{1，2 n -1}，S 0 = W 1 。 ② 找出总线上响应时间次小的报文P 2 ，此时自由时间S 1 = T 2 − D 1 × t f 。若S 1 > 0，则表明P 2 待P 1 发出后不会超时，有S 1 的时间可以缓冲等待。此时P i 的优先级设置为1，P 2 的优先级暂定为2。若S 1 < 0，则表明P 2 待P 1 发出后会超时，没有时间可以缓冲等待。此时P 1 的优先级设置为2，P 2 的优先级暂定为1。S 1 = t 1 − D 2 × t f ，若此时S j < 0，则报文发生死锁，表明那个报文先发送都会导致超时，优先级配置退出。 ③ 继续找出总线上响应时间次小的报文P 3 ，并且比较S 2 = t 3 − (D 1 + D 2 ) × t f ，若S k < 0，则需要对前面报文的优先级进行调整，调整的原则是t 2 < max{S 0 ，S 1 }。若t 2 > S 1 ，则表明该报文插入队列后会导致P 2 延时，该调整无效。若t 2 < min{S 0 ，S 1 }，则报文P 3 插入P 1 前面，P 1 ，P 2 的优先级依次递降1，S 0 = S 0 − t 2 ，S 1 = S 1 − t 2 。若t 2 > S 0 且t 2 < S 1 ，则P 3 插入P 2 前面。此时，P 2 之前由于插入了P 3 ，相应的自由时间S 1 = S 1 − t 2 。 ④ 按照上述方法②，③找出总线上响应时间次小的报文P i ，S i−1 = t i − (D 1 + D 2 + … + D i ) × t f ，若S i−1 < 0，则需要对前面报文优先级进行调整，调整的原则是t i < max{S 0 ，S 1 ，…，S i−1 }。若t i > S i−1 ，则表明该报文插入队列后会导致P i−1 延时，该调整无效。若t i < min{S 0 ，S 1 ，…，S i−1 }，P i 报文插入P 1 之前，后续报文的时间自由度做调整，S 0 = S 0 − t i ，S 1 = S 1 − t i ，…， S i−1 = S i−1 − t i−1 。若t i < S j ，且t i > S j−1 ，S j ∈{S 0 ，S 1 ，…，S i−1 }，则P i 插入P j+1 前面，后续报文的时间自由度做如下调整，S 0 = S 0 − t i ，S 1 = S 1 − t i ，…， S i−1 = S i−1 − t i−1 。 报文因超时的紧迫性需要加速发送时，通过调整优先级插入到队列之中。保证了前面的报文优先级不变，后面的报文优先级依次递降1个单位。