嵌入式装置可视化页面程序代码处理架构设计

2017-05-12 09:41刘国伟陈宏君刘克金
单片机与嵌入式系统应用 2017年5期
关键词:代码生成代码页面

刘国伟,陈宏君,刘克金

(南京南瑞继保电气有限公司,南京 211102)

嵌入式装置可视化页面程序代码处理架构设计

刘国伟,陈宏君,刘克金

(南京南瑞继保电气有限公司,南京 211102)

提出一种灵活的嵌入式装置可视化页面程序的代码处理架构。基于元件的层次模型,形成相关数据结构和功能调用函数。通过在脚本中调用代码生成器开放的接口,可定制形成不同运行场景的代码。通过扩充解析预处理函数,支持形成高效紧凑的代码。采用通用模板替换的方法,可自动形成多种处理器的编译文件。本文提出的技术已经在电力系统保护控制装置开发中进行了批量应用,显著提升了开发效率和质量。

嵌入式装置;可视化编程;代码生成;编译

引 言

嵌入式装置是嵌入对象系统中用于执行独立功能的专用计算机[1], 早期由于硬件资源和性能约束,一般用汇编语言或语言开发应用程序。随着硬件性能的提升, 图形化编程、可视化调试成为一种可行趋势[2-6]。面向对象的图形化软件开发方法,用图形化功能块搭建程序,以直观方便、易于理解的方式构建应用程序功能,在电力系统保护测控中得到了应用[7-9]。在可视化编程使用过程中,面临硬件平台更新换代周期加快、系统软件的接口可能发生变化、支持嵌入式装置运行和PC机虚拟仿真等环境切换、提升代码运行效率等挑战,需要设计灵活高效的代码生成和处理架构,提升可视化编程的灵活性、可靠性。

1 嵌入式平台分层架构

图1 嵌入式平台分层架构

如图1所示,嵌入式控制保护平台由三大部分组成:硬件平台、系统软件、可视化编程软件[2]。在平台的最上层,就是基于平台开发的各种装置应用程序,UAPC(统一的控制保护)平台+应用功能就构成一个完整的控制保护系统。本文的可视化编程软件作为UAPC控制保护平台的一部分,是衔接应用和底层软件的桥梁,对下屏蔽了不同版本硬件和系统软件的接口差异,对上则需适配不同应用场景的开发需求。各个方向的应用基于通用符号库和应用符号库来开发图形化程序。编程软件分析图形化页面,形成嵌入式装置代码和配置文件,并调用编译器编译形成目标文件。

2 可视化层次数据模型设计

参考IEC61131-3的概念定义[10],采用层次数据模型组织整个装置的程序结构。

如图2所示,可视化层次数据模型设计如下:

① 装置:相当于IEC61131-3标准定义的可编程控制系统,位于软件模型最上层,装置是1个特定类型的控制系统,包括硬件、处理资源、I/O通道、运行的程序,反映了可编程控制器的物理结构,装置包括若干插件。

② 插件:位于软件模型的第2层,为运行程序提供支持系统,为程序和I/O通道提供界面和接口,提供一个支持系统运行的程序,其中具有多核处理器的插件可加装、启动、运行多个独立的程序,插件包括若干元件。

③ 元件:完成特定应用功能的面向对象的一组数据和对数据进行处理的过程,处理后输出的数据供其他元件进一步使用[9]。元件包含输入、输出和参数等外部接口,由若干等级任务组成,可把插件的程序拆分为粒度适中的若干元件。

④ 任务:用于规定程序组织单元在运行期的特性,是一个执行控制元素,具有调用能力,可周期或事件触发执行,包括若干程序页面。在可视化工程中,采用图形化任务链来设置页面等级和执行顺序,通过元件执行链来设置元件实例的执行顺序。

⑤ 页面:由库元件、符号和符号之间输入-输出数据连线组成,页面功能形成1个函数,可添加到任务队列,通过绘制图形化符号和数据连线搭建应用逻辑。

图2 可视化层次数据模型

3 代码生成技术

支持以元件、插件、装置为单位形成代码。可视化代码生成主要步骤为:前端模块读取可视化工程和符号库,形成可视化页面内存数据模型;对页面符号进行拓扑排序,形成符号调用执行顺序;启动脚本执行引擎,在脚本中可获取符号的属性,脚本执行后将数据存储到中间件;后端模块组织文本段落,输出代码文本;最后形成Makefile,并调用不同CPU/DSP的编译器,形成目标文件。

在设计时,代码生成工具面临两个挑战:一是相同的可视化程序会在不同的环境下运行,例如嵌入式装置、Windows的PSCAD仿真软件、Linux的Hypersim仿真软件,这些场景下的数据对象、代码文件组织方式有差异(嵌入式装置以插件为单位编译,PC机仿真以装置为单位编译,需增加前缀处理重名、增加插件间连线代码等),支持一种新的应用场景时,不能影响已经稳定的模块。二是形成的代码文本中有系统软件的接口函数,当系统软件升级时,尽量不修改组件源代码,需提高灵活性。通过采用加载不同后端产物生成组件方式实现平滑切换,采用脚本定义符号行为的方式来实现和底层软件的解耦。代码生成整体处理架构如图3所示。

图3 代码生成处理架构

3.1 元件代码模型

图4 元件代码文件结构

可视化元件对应一个h、c文件。如图4所示,在h文件中定义元件数据结构体(包括输入变量、输出变量、参数、内部变量)和声明接口函数,在c文件形成库函数、页面函数、任务调用函数、元件构造、元件初始化函数。在元件构造函数中分配数据结构体,并调用系统接口注册接口变量信息;在初始化函数中完成变量初始化,并将任务函数添加到任务队列中。

以一个过压元件为例, 其形成的数据结构体示例如下:

struct OverVoltage {

#include"basecomp.h"

unsigned short* UA; //A相电压

unsignedshort* UB; //B相电压

unsignedshort* UC; //C相电压

unsigned char FD; //启动

unsigned char Op; //动作

unsigned int U_Set; //电压定值

intOpt_Curve; //延时特性

… };

在c文件中,依次形成newOverVoltage、initOverVoltage等函数,例如在元件构造函数代码示例如下:

Component* newOverVoltage(void* parent, char* name){

OverVoltage* dp = calloc(1, sizeof(OverVoltage));

if(!dp)return NULL;

//调用系统平台的注册接口

defineComp(dp, parent, name);

defineIn(dp, &&dp->UA,"UA tp=us");

defineOut(dp, &dp->Op,"Op tp=uc");

definePara(dp, &dp->U_Set,"U_Set tp=ui");

……

return (Compoent*)dp;

}

代码生成工具分析页面中的输入-输出符号,形成对应变量定义、变量注册代码,分析库元件、功能块函数符号和连线,形成对应的函数调用代码。

3.2 数据中间件设计

为了能够形成图4模型的元件代码,设计了代码文本处理数据中间件,对h/c文件进行了抽象建模,将文本的结构分为如下几类:

enum SemanticType{

SBASE_TYPE=0,

SINCLUDE_TYPE, //include

SCOND_COMPILE_TYPE, //条件编译

SVAR_TYPE, //变量声明

SMACRO_TYPE, //宏定义

SENUM_TYPE, //枚举定义

SFUNC_TYPE, //函数声明和定义

SSTRUCT_TYPE, //结构体定义

SFILE_TYPE, //源文件定义

STEXT_TYPE, //各种代码段

SOTHER_TYPE

};

其中STEXT_TYPE是代码片段,又细分为头文件定义段、变量定义段、本地函数段、页面new函数段、页面init函数段、页面运行函数段、元件new函数段、元件init函数段等。其UML结构如图5所示。

图5 数据中间件模型

将这些段落顺次拼接汇总,形成元件的h/c代码文本。代码段定义为CSection类,包括若干前置代码、函数代码、后置代码等,在文件实例中创建若干代码片段,调用接口向相关段落中添加变量、函数等内容。

3.3 脚本调用技术

基于跨平台C++/QT开发的代码工具,从QObject基类继承的相关类可定义若干SLOT函数,并向脚本引擎中注册指针对象,从而脚本中可调用对象实例的SLOT函数(定义为API接口)。API接口提供可视化编程软件的开放服务功能,在脚本中调用API来定义编程符号的代码输出内容,通过这种解耦方式,应用开发人员在不需要掌握平台内部工作细节的前提下,即可使用相关软件或硬件接口,并且平台升级时,只需刷新符号块,应用程序页面不需要修改。向脚本引擎注册的对象有代码生成器coder、装置实例app、当前处理的插件board、当前处理的元件comp、当前处理的页面page、当前处理的符号symb等。以1个PAM跳闸矩阵符号为例,脚本调用示例如下:

#set func code

pamna='PAM_'+pamid;

s=' '

s+='static void'+pamna+'()'

for i in range(num):

sidx=('%d'%(i+1))

if i<(num-1):

s+='Uint8 a'+sidx+','

if ((i+1)%5)==0:

s+=' '

else:

s+='Uint8 a'+sidx+') '

s+='} '

coder.cout(s,'LOCAL_FUNC')

3.4 提高运行效率设计

嵌入式装置由于实时性的要求,对程序运行效率要求极高,可视化程序设计和处理中,可通过如下措施,尽可能地提高程序运行效率:

① 高质量的模块化符号库设计。基于松耦合、高内聚的原则,对各种保护测控功能进行合理粒度的划分,形成模块名和功能定义。统一的标准子程序库对常用的小模块(如付氏滤波算法,延时算法等)进行标准化函数库设计和严格的性能、功能测试,通过集体评审和优化,形成高质量、高可靠、可重用的符号库,则可视化页面是高质量的子程序的组合关系。

② 为了节省代码空间,尽量将运行代码放入到片内。通过合理设置ldf文件,并在元件页面的任务函数前面指定section存放标记,编译链接时可最大程度地将运行函数放入到片内执行。在节省代码空间方面,支持将部分可视化页面进行组合封装,形成复用库,一处功能多处实例,调用相同的代码,从而减少冗余代码。

③ 在功能块函数建模阶段,定义函数原型代码时,扩充条件预处理语句,在代码生成阶段处理相关语句,输出条件对应的分支代码。引入并扩充条件预编译语句,定义#if、#elif、#else、#endif关键字,条件语句包含参数设置值的加减乘除四则运算,并扩充支持C库函数,开发了C预处理解析器,能计算含C库函数的表达式。例如某个功能块在初始化阶段运行的代码是根据时间单位的设置情况决定变量的初始值。其示例如下:

#if( strcmp(time_unit, "USEC") == 0 )

{ time_intel = (int)time_val / 10; }

#elif( strcmp(time_unit, "MSEC") == 0 )

{ time_intel = (int)time_val * 100;}

当time_unit的设置值为USEC时,只形成如下代码:

time_intel = (Uint32)time_val / 10;

避免采用if-else语句在运行过程中进行条件判断,有效地提高了自动生成代码的执行效率,并节省了代码空间。

4 可配置模板的Makefile形成技术

由于不同的编译器其Makefile文件格式不同,如果每新增一种处理器就修改处理程序,存在工具软件和硬件平台紧耦合的问题。故设计了一种可配置模板的Makefile通用形成技术,将配置模板分为如下几段:

① Tool:编译前调用的文件操作、目录操作命令格式模板;

② Lib:需链接的系统库,支持通配符替换;

③ Inc:依赖的头文件查找目录列表,提供一些默认的文件目录,并可扩充新的目录;

④ Flag:编译选项、链接选项;

⑤ Obj:需链接的二进制目标文件,不同编译器文件后缀可不同;

⑥ Compile:执行编译过程命令链,依次包括形成单个c文件的obj、将obj文件链接为目标文件、将目标文件转换为Hex文件的命令序列。

整个编译链接过程如图6所示。

图6 编译链接过程

基于通用模板方法,当新增一种新的处理器时,只需在配置目录增加一份新的编译模板,并在配置文件设置插件的处理器型号和模板文件的关联关系,按照预定的关键字和通配符,代码生成工具可自动形成对应的Makefile文件,实现了可灵活增加新的处理器型号。

结 语

[1] Elecia White.嵌入式系统设计与实践[M].北京:机械工业出版社,2013.

[2] 李响,刘国伟,冯亚东,等.新一代控制保护系统通用硬件平台设计与应用[J].电力系统自动化,2012,36(14):52-55.

[3] 王培进,李晓路.嵌入式系统集成开发平台的设计与实现[J].计算机应用与软件,2012,29(5):10-13.

[4] 陈宏君,刘克金,冯亚东,等.新一代保护测控装置配套工具软件设计与应用[J].电力系统自动化,2013,37(20):92-96.

[5] 刘克金,陈宏君,冯亚东,等.新一代控制保护系统可视化编程软件设计与实现[J].工业控制计算机,2014,27(10):82-87.

[6] 陈宏君,冯亚东,文继锋,等.嵌入式程序动态分配内存的调试方案设计[J].单片机与嵌入式系统应用,2015(9):18-21.

[7] 姚成,黄国方,周邵亮,等.软PLC技术应用于智能保护测控装置的实现方案[J].电力系统自动化,2010,34(43):115-117.

[8] 仲伟,丁宁,吴参林,等.图形化编程的继电保护平台软件平台设计[J].电力系统保护与控制,2011,39(3):100-147.

[9] 陈宏君,熊蕙,文继锋.嵌入式系统面向对应的多层次复用架构[J].单片机与嵌入式系统应用,2016(9):8-11.

[10] 彭瑜,何衍庆.IEC61131-3编程语言及应用基础[M].北京:机械工业出版社,2012.

[11] 冯亚东,刘克金,陈宏君,等.一种用于可视化编程的功能块函数建模方法:中国, 201210036681.8[P],2012-08-01.

刘国伟(高级工程师),主要研究方向为嵌入式平台软硬件开发和管理;陈宏君、刘克金(高级工程师),主要研究方向为可视化编程软件开发。

Visual Graph Code Processing Architecture for Embedded Device

Liu Guowei,Chen Hongjun,Liu Kejin

(NR Electric Co.,Ltd.,Nanjing 211102,China)

In the paper,a flexible visualization program processing architecture for embedded device is proposed.Based on the hierarchy component model,the data structure and function call function are formed.By calling the open API interface in the script,the tool can be used to generate code for different application scenarios.By executing the preprocessing function,the tool supports the formation of highly efficient and compact code.Using the common template replacement method,the tool can automatically form a variety of processors compiled files.The technology has been applied in the development of power system protection and control devices,which significantly improves the efficiency and quality of development.

embedded system;visual graph coding;code generation;compile

TP393

A

士然

2017-01-03)

猜你喜欢
代码生成代码页面
刷新生活的页面
Lustre语言可信代码生成器研究进展
创世代码
创世代码
创世代码
创世代码
代码生成技术在软件开发中的应用
基于XML的代码自动生成工具
网站结构在SEO中的研究与应用
基于关系数据模型代码生成器的设计与实现