本文主要是介绍便携式航电实时系统测试平台调度及描述语言介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- 进程调度服务
进程调度台是整个运行态的控制点。它按用户指令载入测试设计端编制的测试项目,并指挥整个运行态,执行测试项目中的测试用例。
进程调度台向运行态各组件发布指令,以对测试用例实施启动、切换、执行、重置、终止等操作。随着测试规模的增大,进程调度台变得更为重要。
在执行测试前,首先要启动进程调度台,它是一个后台驻留程序,启动后驻留在任务栏中,主要用于测试执行期间的进程调度和服务。进程调度台在桌面的快捷方式如下图所示:
- 1 进程调度台
进程调度台启动后的界面如下图所示:
- 2 进程调度台界面
点击界面右上角的“X”关闭按钮,进程调度台隐藏在操作系统任务栏中。进程调度台启动后,可管理测试过程中的进程,实现对内存的管理。
进程调度台在指定的端口接收来自远程的命令,每台相关的客户端计算机都需要运行一个实例。进程调度台的存在使得客户端计算机便于与服务器端相连接,在测试执行时可以在测试执行服务的管理下自动启动测试执行客户端。
注:没有启动进程调度台,环境设置时会失败,在界面下端的输出窗口会有红色严重错误提示:检查进程调度台【模型服务器127.0.0.1】失败!
本文介绍ETest采用的ICD描述方法:使用DPD协议描述语言进行描述。
嵌入式设备通信协议定义语言(简称DPD语言)是一种编译型语言。编译的结果是带有强命名的协议数据,可以对接口通信数据进行编码/解码。
DPD语言具有较强的描述能力,能够进行整形数据、浮点型数据、字符型数据的定义还可以进行分支结构、循环结构的定义。对于非整字节的定义,能够按位长度进行定义。
DPD语言描述的单位是“协议”。每个“协议”包含若干个“字段”。
每个协议的定义都是用Protocol关键字和End关键字括起来的一段代码。
语法:
Protocol Name [协议段]{1,*} End
例子:
Protocol Protl Segment Head StandardUInt32 Default=0 ByteOrder=Small Segment Type StandardUInt8 Default=0 Segment Length StandardUInt32 Default=0 ByteOrder=Small Segment Tail StandardInt8 Default=0 Segment CheckBit StandardUInt8 Default=0 End |
定义协议以Protocol关键字开始。
有效字符:字母,汉字,数字,下划线。
约束:不能以数字开头。
定义协议里所包含的协议段,至少有1个协议段,不限制最多数量。
本文约定:
{n,*}:表示至少n个,最多不限。
{n,m}:表示至少n个,最多m个,其中m > n。
{*}:表示任意个。
关闭协议定义,针对该协议的所有定义结束。
语法:
Segment Name Type [修饰][注释]
例子:
Protocol COMW Segment Head StandardUInt32 Default=0 ByteOrder=Small #注释 End |
1) Segment
协议段定义开始。
2) Name
有效字符:字母,汉字,数字,下划线。
约束:不能以数字开头。
3) Type
协议段类型,基本类型包括整型、浮点型和布尔类型;此外,还支持字符串、校验字段、数组、子接口、协议块、计算字段。
4) 修饰
针对每种Type都有不同的修饰语法,详见后面章节。
5) 注释
注释以#开头,至该行的末尾。
整形协议段的类型如下表所示:
整形协议段类型
类型 | 定义 | 取值范围 |
StandardInt32 | 有符号32 位整数 | -2,147,483,648到 2,147,483,647 |
StandardUInt32 | 无符号32 位整数 | 0 到4,294,967,295 |
StandardInt16 | 有符号16位整数 | -32,768 到32,767 |
StandardUInt16 | 无符号16位整数 | 0 到65,535 |
StandardInt8 | 有符号8位整数 | -128 到127 |
StandardUInt8 | 无符号8 位整数 | 0到255 |
RandomInt | 任意长度整数 (VXWorks下位机暂不支持) | 根据长度确定 |
RandomUInt | 任意长度无符号整数 (VXWorks下位机暂不支持) | 根据长度确定 |
语法:
Segment name StandardInt32 [Default=*] [Format=*] [ByteOrder=*]
Segment name StandardUInt32 [Default=*] [ByteOrder=*]
Segment name StandardInt16 [Default=*] [Format=*] [ByteOrder=*]
Segment name StandardUInt16 [Default=*] [ByteOrder=*]
Segment name StandardInt8 [Default=*] [Format=*]
Segment name StandardUInt8 [Default=*]
Segment name RandomInt Length=9 Default=0 Format=Complement
Segment name RandomUInt Length=9 Default=0
例子:
Protocol COMW Segment data1 StandardInt32 Default=0 Format=Complement ByteOrder=Small Segment data2 StandardUInt32 Default=0 ByteOrder=Small Segment data3 StandardInt16 Default=0 Format=Complement ByteOrder=Small Segment data4 StandardUInt16 Default=0 ByteOrder=Small Segment data5 StandardInt8 Default=0 Format=Complement Segment data6 StandardUInt8 Default=0 End |
浮点型协议段的类型如下表所示:
浮点型协议段类型
类型 | 大致范围 | 精度 |
StandardDouble | ±5.0 × 10 −324 到 ±1.7 × 10 3012 | 15 到 16 位 |
StandardFloat | -3.4 × 10 312 到 +3.4 × 10 312 | 7 位 |
语法:
Segment name StandardDouble [Default=100]
Segment name StandardFloat [Default=100]
例子:
Protocol COMW Segment data1 StandardDouble Default=1.0 Segment dtat2 StandardFloat Default=1.0 End |
Boolean
表示一个开关量,取值为True或者False,对应内存中的一个Bit。
语法:
Segment I2 Boolean [Default=True/False]
例子:
Protocol COMW Segment data1 Boolean Segment data2 Boolean Default=True Segment data3 Boolean Default=False End |
注:本类型在VXWorks实时下位机暂不支持。
-
-
- IF分支
-
IF分支的内容根据某个字段值的变化而有所变化。
语法:
Segment I3 If name==1
Then subProtocol1
Else subProtocol2
例子:
Protocol SubProtocol1 Segment val1 StandardInt16 Default=0 Format=Complement ByteOrder=Small End Protocol SubProtocol2 Segment val2 StandardInt16 Default=0 Format=Complement ByteOrder=Small End Protocol Main Segment name StandardInt8 Default=0 Format=Complement Segment value IF name==True Then SubProtocol1 ELSE SubProtocol2 End |
注:本类型在VXWorks实时下位机暂不支持。
-
-
- SWTICH分支
-
SWITCH分支字段根据某个字段的值的不同进入不同的分支。
语法:
Segment I2 Switch segVal
Case 1 SubProtocol1
Case 1 SubProtocol2
Default SubProtocol3
例子:
Protocol SubProtocol1 Segment val1 StandardInt16 Default=0 Format=Complement ByteOrder=Small End Protocol SubProtocol2 Segment val2 StandardInt16 Default=0 Format=Complement ByteOrder=Small End Protocol SubProtocol2 Segment val2 StandardInt16 Default=0 Format=Complement ByteOrder=Small End Protocol Main Segment SegName StandardInt8 Default=0 Format=Complement Segment I2 Switch SegName Case 1 SubProtocol1 Case 2 SubProtocol2 Default SubProtocol3 End |
注:本类型在VXWorks实时下位机暂不支持。
-
-
- 校验字段
-
校验字段是指按照一定的校验算法,对协议数据进行校验,生成校验数据所形成的字段。
校验字段的定义方法如下:
Protocol COMW Segment data1 StandardUInt8 Default=0 Segment data2 StandardUInt8 Default=0 Segment data3 StandardUInt8 Default=0 Segment data4 StandardUInt8 Default=0 Segment Check CRC Range=(0,10) Algorithm=CRC_16_0X1021 BitCount=8 End |
其中最后一个字段为校验字段。Check为字段名;CRC为协议字段的关键字;Range为指定校验数据的范围(以位为单位),不写默认为前面所有数据;Algorithm属性表示使用的协议算法名。BitCount属性为校验值的长度(以位为单位)。
发送数据时,校验字段自动根据所指定的校验算法,计算出校验字段的值。
接收数据时,校验字段自动根据所指定的校验算法,计算出校验字段的值,并与所接收的校验字段的值进行比较,在测试脚本中可通过校验字段的Checked属性(Proto1.Check.Checked,Proto1为仿真模型协议线的名称)来判断校验值是否正确。校验值相同,Checked的值为True;校验值不同,Checked的值为False。
注:
1:源数据范围:默认的源数据从协议头开始,到定义的协议字段为止;
可通过Range属性修改校验范围,使用方法为:Range=(a,b)
a 为起始bit的序号;b为结束bit的序号;当b=-1时代表至校验字段前。
Range(0,15),表示从0号位开始,至15号位;
Range(16,0),表示从16号位开始,至校验字段前。
2:对Windows下位机,系统提供如下的协议算法(Algorithm),用户还可根据需要自己定义(见章节2.4.7:CRC生成):
CRC_SUM_8(按字节相加,大端序);
CRC_Check_Sum(按字节相加,小端序);
CRC_SUM_16(按双字节相加,结果的字节序按小端序);
CRC_SUM_16_2(按双字节相加,结果的字节序按大端序);
CRC_SUM_32(按四字节相加,结果的字节序按小端序);
CRC_SUM_32_2(按四字节相加,结果的字节序按大端序);
CRC_XOR_8(按字节或);
CRC_XOR_16(按双字节或,结果的字节序按小端序);
CRC_XOR_16_2(按字节或,结果的字节序按大端序);
CRC_XOR_32(按四字节或,结果的字节序按小端序);
CRC_XOR_32_2(按字节或,结果的字节序按大端序)
用户可以自己开发CRC插件。
开发方式目前有两种:C和C#。
第一种开发方式:C的插件开发方式:
a) 提供如下的导出 函数:
extern "C" __declspec(dllexport) wchar_t * CRCDescript()
这个函数返回该插件的名称,注意名称需要符合 [标示符]的规范。
b) 提供如下导出函数:
extern "C" __declspec(dllexport) void CalcluteCRC(const unsigned char* data,const int data_len, unsigned char* const sum,unsigned int sum_len)
这个函数用于计算校验值。
参数:
const unsigned char* data:需要校验的数据。
const int data_len:需要校验的数据的长度。
unsigned char* const sum:校验值数据。
unsigned int sum_len:校验值数据长度(以位为单位)。
注:校验值数据长度只能为8的整数倍。
范本如下:
#include "stdafx.h" #include "CRCLib.h" #include <cstddef> // for std::size_t #include <iostream> // for std::cout #include <Objbase.h> #include <numeric> using namespace std; extern "C" __declspec(dllexport) wchar_t * CRCDescript() { wchar_t *str=L"CRC_Check_Sum"; size_t len=wcslen(str)+1; wchar_t *desc = (wchar_t*)::CoTaskMemAlloc(len*sizeof(wchar_t)); swprintf_s(desc, len, str); return desc; } extern "C" __declspec(dllexport) void CalcluteCRC(const unsigned char* data,const int data_len, unsigned char* const sum,unsigned int sum_len) { unsigned long checksumT=::accumulate(data,data+data_len,0); ::memcpy(sum,&checksumT,sum_len); for(int i=0;i<sum_len/2;++i) { unsigned char t=sum[i]; sum[i]=sum[sum_len-i-1]; sum[sum_len-i-1]=t; } } |
第二种开发方式:C#的插件开发方式:
建立一个类,从 Kiyun.EmbedTest.Protocol.CRCLibCore.CS_CRCAlgorithm继承;并且完成下面两步:
1) 在构造函数中为Name字段赋值为校验算法的名称(同协议中的Algorithm属性值一致)。
2) 实现 CalcluteCRCFunc 方法,在方法体中完成校验算法的实现;这个方法包含两个参数:bitData参数是校验的输入数据;sum_bit_len是计算后的校验字段的位数。
在校验实现算法程序中,可使用Console.Write输出调试信息到控制台。
编写完成的算法生成DLL动态链接库。动态链接库的名称必须以“CRC_”开头,否则系统加载不成功。
范本如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace KiyunCRC8 { public class CRC8 : Kiyun.EmbedTest.Protocol.CRCLibCore.CS_CRCAlgorithm { byte [] CRC8Table= new byte[256]{ 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53}; public CRC8() { this.Name = "Kiyun_CRC8"; } private byte getByte(IEnumerable<bool> bitData, int offset) { System.Collections.BitArray bit8 = new System.Collections.BitArray(8); for (int i = 0; i < 8; i++) bit8[i] = bitData.ElementAt(offset + i); byte[] byteArray = new byte[1]; bit8.CopyTo(byteArray, 0); return byteArray[0]; } protected override System.Collections.Generic.IEnumerable<bool> CalcluteCRCFunc(System.Collections.Generic.IEnumerable<bool> bitData, uint sum_bit_len) { if (sum_bit_len != 8) return null; var ret = new bool[(int)sum_bit_len]; byte crc8 = 0; int len = bitData.Count(); byte byteData = new byte(); int offset = 0; byteData = getByte(bitData, offset); while(offset<len) { crc8 = CRC8Table[crc8 ^ byteData]; offset += 8; if (offset >= len) break; byteData = getByte(bitData, offset); } byte[] crcRet = new byte[1]; crcRet[0] = crc8; System.Collections.BitArray retByte = new System.Collections.BitArray(crcRet); for (int i=0;i<sum_bit_len;i++) { ret[i] = retByte[i]; } return ret; } } } |
对VXWorks下位机,仅支持CRC_16和CRC_32两种校验算法。
-
-
- 数组字段
-
在协议中可以定义某个协议段为数组类型。数组的长度可以是固定长度的,也可以是可变长的。数组元素是一个子协议。
定义数组协议段的关键字是Array。它有两个属性,Count和Child。Count表示数组的长度。Child指名数组元素的类型。
如果Count的值是一个常量,则数组的长度是固定的。如果Count的值是一个已定义的协议段的名称,则数组的长度在运行中由协议段的值决定。
具体的例子如下:
1) 固定长度的数组
Protocol T Segment data1 StandardUInt8 Default=0 Segment data2 StandardUInt8 Default=0 Segment data3 StandardUInt8 Default=0 Segment data4 StandardUInt8 Default=0 End Protocol P Segment Head StandardUInt8 Default=0 Segment Data Array Count=3 Child=T End |
- 2)可变长度的数组
Protocol T Segment data1 StandardUInt8 Default=0 Segment data2 StandardUInt8 Default=0 Segment data3 StandardUInt8 Default=0 Segment data4 StandardUInt8 Default=0 End Protocol P Segment Head StandardUInt8 Default=0 Segment ArryaCount StandardInt8 Default=0 Segment Data Array Count=ArryaCount Child=T End |
以上是数组字段在协议中的定义方式。下面简要介绍一下协议字段的值在测试脚本中的引用方式,其中Proto1为仿真模型协议线的名称。
a) 数组的长度
Proto1.Data.Count
b) 为数组里的元素进行赋值
Proto1.Data[0].data1.Value=11
Proto1.Data[0].data2.Value=22
Proto1.Data[0].data3.Value=33
c) 读取数组里的元素值
Proto1.Data[0].data1.Value
在协议中可以定义字符串类型的字段。
语法:
Segment name String Code='GB2312' Tail='&' Default='kiyun'
例子:
Protocol p1 Segment name StandardInt8 Default=0 Format=Complement Segment S5 String Code='GB2312' Tail='&' Default='kiyun' End |
其中String是字符串类型的关键字;Code是编码方式;Tail是结束标志;Default是默认值。
注:本类型在VXWorks实时下位机暂不支持。
在协议中可以定义协议块的字段。
语法:
Segment name Block Child=P
例子:
Protocol p1 Segment name1 StandardInt8 Default=0 Format=Complement Segment name2 StandardInt8 Default=0 Format=Complement Segment name3 StandardInt8 Default=0 Format=Complement End Protocol p2 Segment name4 StandardInt8 Default=0 Format=Complement Segment name5 Block Child=p1 End |
其中p1是本协议段之前出现的一个协议段的名字;Block是一个字块;Child是该字块的协议模板。
在协议中可以定义字节块的字段。
语法:
Segment P Buffer Count=1
例子:
Protocol p1 Segment name StandardInt8 Default=0 Format=Complement Segment P Buffer Count=10 End |
其中P是字节块类型的关键字;Buffer是字节块的缓冲区;Count是统计字节块数;默认值为1。
注:本类型在VXWorks实时下位机暂不支持。
每个协议定义单元中,可以定义多个协议(多个用Protocol和End括起来的主体。)
定义的最后一个协议是主协议,其余为附属协议。协议数据的编码解码是从主协议开始的。
主协议中可以含有对附属协议的引用。如在IF协议端、SWITCH协议段或数组协议段中。
下表列出数据类型关键字:
数据类型关键字
名称 | 描述 |
StandardInt32 | 标准32位整数 |
StandardUint32 | 标准32位无符号整数 |
StandardInt16 | 标准16位整数 |
StandardUint16 | 标准16位无符号整数 |
StandardInt8 | 标准8位整数 |
StandardUint8 | 标准8位无符号整数 |
StandardDouble | 标准双精度浮点数 |
StandardFloat | 标准浮点数 |
Boolean | 布尔,占用1Bit空间 |
CRC | 校验字段类型 |
Array | 数组字段类型 |
String | 字符串类型 |
Block | 协议块 |
Buffer | 字节块 |
下表列出其他关键字。
其他关键字
名称 | 说明 |
Protocol | 定义协议 |
Segment | 定义协议段 |
End | 协议定义结束 |
Format | StandardInt32、StandardInt16、StandardInt8、RandomInt类型字段的属性, 代表存储格式:原码,补码还是反码 |
Primitive | Format字段的可取值之一,表示原码 |
Inversion | Format字段的可取值之一,表示反码 |
Complement | Format字段的可取值之一,表示补码 |
ByteOrder | StandardUInt32、StandardInt32、StandardUInt16、StandardInt16类型字段的属性, 代表字节存储顺序 取值包括:Small、Big。默认为Small |
Big | ByteOrder字段的可取值之一 大端,整数的高位字节位于内存的前端 |
Small | ByteOrder字段的可取值之一 小端,与Big相反 |
Length | RandomInt,RandomUInt字段的属性, 代表的长度(按位),范围(1-32) |
Algorism | CRC字段的属性,代表校验函数 |
BitCount | CRC字段的属性,代表位数 |
Count | Array字段和Buffer字段的属性,代表长度 |
Child | Array字段和Block字段的属性,代表子协议 |
Code | String字段的属性,代表编码方式 |
Tail | String字段的属性,代表结束标识 |
If | 条件判断语句 |
Then | 条件为真时的分支 |
Else | 条件为假的分支 |
Switch | 数值判断语句 |
Case | 数值分支 |
Default | 默认值分支 |
这篇关于便携式航电实时系统测试平台调度及描述语言介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!