西门子CPU模块6ES7515-2AM02-0AB0
引言
调试是开发过程中必不可少的环节,然而内核、嵌入式系统的调试不同于传统的调试系统。通常嵌入式系统不具备使用本地调试器的能力,由于:
系统自身的资源有限。内存小,输入输出设备不能用于调试。
传统的调试系统需要文件系统,嵌入式系统通常无文件系统,内核调试时还不支持文件系统。
调试器的运行本身需要操作系统的支持,因此无法实现操作系统内核的调试。
有效的解决方法是采用远程调试技术。远程调试是指调试器运行的环境(主机)和被调试的系统(目标机)在物理上是分离的,通过串口或者网络进行连接的调试技术。
GNU免费提供的GDB就拥有强大的远程调试功能,它能够使开发人员以远程调试的方式单步执行目标平台上的程序代码、设置断点、查看内存,并同目标平台交换信息。GDB远程调试的实时、动态、方便、免费等优点使它逐渐成为嵌入式开发的调试方案。
远程调试系统由三部分组成:主机上的本地调试器,目标机上的调试代理,远程调试协议。如图1。对应于GDB远程调试系统的三部分:GDB,GDBstub, GDB远程串行协议。下面就这三部分进行分析。
图1. 远程调试系统
2、RSP协议
GDB RSP(Remote Serial Protocol)定义了GDB宿主机与被调试目标机进行通信时数据包的格式。信息的格式是:$数据#校验码。多数的信息都使用ASCII码,数据由一系列的ASCII码组成,校验码是由两个16进制数组成的单字节校验码。接受方接受数据并校验,若正确则回应“+”,错误则回应“-”。通信的内容包括读写数据、控制程序运行、报告程序状态等命令。RSP的基本命令从通信对话角度可以分为两种:
1) 请求
?:读当前系统状态
g:读所有寄存器
G:写所有寄存器
m:读内存
M:写内存
c:继续执行
s: 单步执行
k:终止进程
2) 答复
“”:告诉GDB上次请求命令不支持。
E:告诉GDB出错
OK:上次请求正确
W:系统在exit_status状态下退出。
X:系统在signal信号下终止。
S:系统在signal信号下停止。
O:告诉GDB控制台输出,这也是唯一向GDB发出的命令
3、GDB远程调试功能
调试内核时通常还没有文件系统,而且多数嵌入式由于自身资源的限制不具备文件系统,因此将与文件系统有关的源文件、目标文件及符号表都存放在主机上,由主机上的调试器处理。同样,调试用的输入输出设备也是由主机提供。主机上的调试器接受用户输入的调试命令并进行预处理,对于有些命令(如breakpoint)的处理就在主机GDB上实现,不需要同目标机进行通信。当然,更多的指令需要在目标机上调试代理上实现的。主机将预处理完之后的命令根据RSP进行封装,发送给目标机上的调试代理,调试代理接受命令后作相应的处理,并返回信息给主机上的调试器。
4、目标机上stub的实现
目标机上stub的基本功能是与主机GDB进行通信,实现读写内存、寄存器,stop,continue。主机GDB同目标机上stub进行通信的通用模型如图2:
图2. GDB同目标机上stub通信的通用模型
目标机与主机通过硬件连接,被调试部分插入stub,GDB与被调试部分通过RSP进行通信。根据stub所处层的不同来实现不同层的调试,包括内核层、应用层的调试。
4.1 内核层调试模型
图3. 使用stub对内核进行调试
如图3,将stub插入到内核里就可以实现内核的调试了。Linux内核调试机制KGDB就是使用这种模式。KGDB可以分为初始化模块和控制模块。
4.1.1初始化模块
修改异常处理函数,使得在异常发生时都进入函数handle_exception(),这样GDB就能够捕获这些异常。初始化之后使用breakpoint()函数将系统控制权直接交给GDB。KGDB对异常处理函数的修改基本上可以分为二种。
定义宏CHK_REMOTE_DEBUG
#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) { if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) { (*linux_debug_hook)(trapnr, signr, error_code, regs) ; after; } }
改变程序的流程,以int3的处理函数为例
#define DO_VM86_ERROR(trapnr, signr, str, name) asmbbbbage void do_##name(struct pt_regs * regs, long error_code) { CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,goto skip_trap) do_trap(trapnr, signr, str, 1, regs, error_code, NULL); skip_trap: return; }
展开DO_VM86_ERROR (3,SIGTRAP,"int3",int3)
asmbbbbage void do_int3(struct pt_regs *regs, long error_code)
{ if (linux_debug_hook != ( gdb_debug_hook *)NULL&&! user_mode(regs))
{ (*linux_debug_hook)(3, SIGTRAP, errorcode, regs);
goto skip_trap;
}
do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
skip_trap:
return;
}
从以上代码可见,进入内核调试状态之后,异常处理函数就是handle_exception(),程序流程跳过了非调试状态时的处理函数do_trap。
不改变程序的流程,以异常divide_error 的处理函数为例
#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) asmbbbbage void do_##name(struct pt_regs * regs, long error_code) { …… do_trap(trapnr, signr, str, 1, regs, error_code, &info); }
展开DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
asmbbbbage void do_divide_error (struct pt_regs *regs, long error_code)
{ if (linux_debug_hook != ( gdb_debug_hook *)NULL&&! user_mode(regs))
{ (*linux_debug_hook)(3, SIGTRAP, errorcode, regs);
}
do_trap(0, SIGTRAP, "divide erro", 1, regs, error_code, &info);
}
从以上代码中看不出调试状态跟非调试状态的区别,然而我们看一下do_trap函数中可能会调用的函数die()。
void die(const char * str, struct pt_regs * regs, long err)
{
CHK_REMOTE_DEBUG(1,SIGTRAP,err,regs,)
do_exit(SIGSEGV);
}
由此可见,调试状态下的异常处理函数还是进入了handle_exception函数。不过与上面一种异常不同之处在于:异常处理函数在调试与非调试状态下的程序流程是相同的,handle_exception只提供获取系统当时的状态,继续运行的结果还是do_exit。
虽然不是所有异常函数都是按上述两种方法定义的,但本质上都可以归划为其一,显然绝大多数处理函数的修改属于第二种,因为种异常就是为调试准备的。因此在目标机具有调试用的输出设备的情况下,完全可以不修改第二种异常处理函数,因为linux内核在非调试状态下的异常处理函数已经输出必要的状态信息、出错信息。
4.1.2控制模块
在控制模块完成与主机GDB的通信,具体流程如图4,handle_exception函数首先判断CPU是否处于VM86模式或用户态,若是则返回,可见KGDB只调试内核态程序。然后接受GDB发来的信息,根据接受的信息作出相应的操作和回复。流程图的虚线框内是所有GDBstub中handle_exception函数的通用流程。
4.2 应用程序调试模型
在嵌入式Linux开发领域里调试应用程序常用调试代理工具GDBserver,其工作原理并不是将stub编译在被调试应用程序内,而是把被调试程序作为GDBserver的子进程,这样GDBserver就可以利用内核提供的代码跟踪机制(ptrace)监控被调试进程的运行,从而来完成调试任务。此工作原理同GDB本地调试相似。其调试模型如图5。GDBserver的工作流程是:GDBserver创建子进程->绑定跟踪ptrace(ptrace_traceme,,)->从主机传来的各种调试命令通过GDBserver转化为各种操作需求的ptrace。显然,如果要用GDBserver来进行远程调试的话,就需要内核操作系统的支持,包括子进程、代码跟踪机制,这样对于其他嵌入式系统内核工作量会比较大。而且ptrace也有其局限性,比如只能跟踪它的子进程,在调试进程和被调试进程之间传送一个长字的数据。使用通用的调试模式工作量会更小。如图6,将stub编译在应用程序中,并在应用程序入口处就插入断点,程序开始就上控制权交给GDB,之后的流程跟内核层调试类似。
图4. GDBKGDB中handle_exception函数流程
图5. 使用GDBserver对应用程序进行调试
图6. 使用stub对应用程序进行调试
5. 不修改内核前提下调试应用程序
GDB实现设置断点的方式是使用内存的读写,即将原指令用一个trap指令代替,使得程序执行到该指令时产生单步调试中断,然后就进入异常处理函数,针对调试器的各种操作处理函数需要作出相应的操作。不同的系统提供不同的调试异常指令,如int3,trap2等,显然对于使用这些硬件平台提供的断点指令为了实现GDBstub调试功能需要改写这些指令异常处理函数。因此一般的调试系统器或调试代理都需要涉及单步调试指令的处理函数,需要系统内核的支持。上面提到的KGDB修改了异常处理函数,GDBserver需要系统内核提供ptrace函数。这种方法存在一些不足之处:修改内核工作量大,移植性差。针对这些情况我们可以采用另一种断点实现方案:在stub中定义一个设置断点函数。
断点函数模拟调试异常指令,实现保护现场、调用异常处理函数、恢复现场并将控制权交给被调试程序。断点函数的基本流程如下。
#define BREAKPOINT __asm__ __volatile__(" bl ent_exception\n)
void debug_trap()
{ __asm__ __volatile__(
" ent_exception: \n"
保存现场
" bl handle_exception \n"
" out_exception: \n"
恢复现场
);
}
handle_exception()函数流程类似图4中的虚线框部分。其中有一点,也是这种方法实现的关键部分是:断点指令的替换。断点设置时从GDB传过来的硬件平台提供的断点异常指令的二进制码,必须将此二进制码替换成在stub中新定义的BREAKPOINT二进制码,这样才能进入调试异常处理函数。因此在handle_exception()函数中,如果收到的请求是“M”,则需要作些处理,流称如图7:
图7. 替换指令
这种方法理论上在内核调试和应用程序调试中都可以使用,但在应用程序的调试中其优点更明显。这种方法在写stub时候不涉及内核,在调试应用程序时不需要切换到内核模式下,直接在用户模式中就可以完成。这种方法也存在些不足之处。为了实现现场保护,要求用户了解系统内的寄存器。随着stub本身复杂度的增加,它的正确性需要更多的检验。
6、结束语
加stub的远程调试方法方便而有效,而且可以降低项目成本,在实际工作中得到广泛的研究和应用。本文提到在不修改内核前提下调试应用程序的方法已成功应用于我们自己开发的微内核结构的操作系统里,为该系统的开发应用提供良好的调试手段。当然加stub的远程调试方法也存在一些不足。显然stub的应用是在串口通信的基础上,因此串口处理函数以及stub自身处理函数的正确性是确保stub安全调试的前提。
一、前言
天铁冶金集团有限公司焦化厂现有58型焦炉两座和JN43-80型焦炉一座,以及配套的备煤、煤气;净化、辅助化工原料回收、污水处理等一套完善的生产系统,年产焦炭112万吨,焦炉煤气5亿立方米,焦油45000吨,粗苯13000吨,硫酸铵15000吨,以及日处理污水2400吨的能力。
随着焦炭产量**,煤气收集压力增大,原抽气鼓风机一运两备的运行方式在夏季高温天气情况下已不能满足生产要求,主要原因是煤气压力增大、温度增高,若不能及时排出将可能发生爆炸。焦炉生产工艺中,集气管煤气压力的控制效果将直接影响焦炉的生产。如果炉内压力过高,会导致焦炉冒黑烟,煤气外泄,严重污染环境,给现场工人的工作和健康造成极大影响和危害;如果炉内压力过低,炭化室将出现负压操作,会吸入大量空气,浪费大量的煤气,严重影响焦炭和煤气的产量和质量,并且长期负压操作将会影响焦炉的正常生产及寿命。
如果要鼓风机实施两运一备运行方式,通过调整回流阀(也称小循环阀)的开度来调节煤气总管压力,由于鼓风机前后压差较大,使得调节阀轻微动作,总管压力就会发生剧烈波动,超过工艺容许范围。因此会引起回炉煤气压力及外网用户煤气量均发生剧变,造成焦炉煤气量不足或外网用户不能正常生产,并且煤气回流造成能量浪费。通过多方调研,焦化厂的技术人员提出使用变频调速来改变鼓风机转速,从而调节集气管的压力方案。
高压变频器的产业化在80年代中期才开始形成,但随着大功率电力电子器件的迅速发展和巨大的市场推动力,高压变频器十多年来的发展非常迅速,使用器件已经从SCR、GTR、GTO发展到IGBT、IECT、IGCT(SGCT)等,功率范围从几百kW到几十MW,技术已经成熟,可靠性得到保证,应用越来越广。天铁冶金集团有限公司焦化厂在考察对比了国内外多家高压变频器生产厂家后,决定选用北京利德华福电气技术有限公司生产的HARSVERT-A系列高压变频器。 ARSVERT-A系列高压变频器性能稳定,可靠性高,并且已在电力、冶金、石化、市政供水、水泥等多个领域成功应用,得到了用户的普遍认可和市场的长久考验。
二、系统方案设计
1.系统电气设计
天铁集团焦化厂有三台D1350-1.237/0.887煤气鼓风机,平时采用一运两备方式,夏季才用两运一备方式。根据实际工况要求设计主回路电气结构图,选用HARSVERT-A型高压变频器一拖一和一拖二成功方案。
1.1电气主回路原理
以1#鼓风机为例说明,工作原理是由3个真空接触器KM11、KM12、KM13以及2个高压隔离开关QS11、QS12组成(见图一),其中KM11、KM12、KM13为高压真空接触器,用于变频和工频的电动切换。QS11和QS12为高压隔离开关,一般情况下处于合闸状态,仅在变频器检修时拉开,用于电机工频运行情况下对变频器进行安全检修。3#、4#风机的主回路工作原理也类似。
特点:
1)可以实现工/变频自动切换功能。在变频器出现严重故障时,系统能够自动切入工频电网中,断开变频器时,负载不用停机,满足现场不能停机要求。
2)易实现一运两备和两运一备运行方式。即一台变频运行,一台变频备用,一台工频备用;两台变频运行,一台工频备用。
1.2 HARSVERT-A高压变频器采用单元串联多电平电压源型拓朴方式
其优点是采用输入多重化设计,高次谐波含量非常小,输出采用单元模块串联,使得谐波含量极低,在无输出滤波器的情况下,可使THD<0.3%,堪称“完善无谐波”高压变频器;极低的转矩纹波和电机噪声;功率因数可达0.95;对电机绝缘无损害,电缆长度无限制;便于冗余设计。中文操作界面便于维修。
2.自动化网路设计
控制系统由主控PLC、旁路柜控制PLC、高压变频器、上位机组成。其中主控系统采用西门子S7-300PLC、旁路柜内置西门子S7-200-PLC、上位机监控选用组态王软件。通讯网路在底层采用Profibus DP总线,主控PLC和上位机监控系统采用以太网通讯。西门子S7-300PLC作为整个系统的控制核心,处理人机界面对系统的各种请求,对整个系统的参数进行监控,实现对集气管压力的PID调节,维持管网的压力恒定。自动旁路柜集成有S7-200PLC,完成变频工频切换功能。上位机系统采用用户熟悉的组态王监控软件,与PLC的连接采用以太网方式。考虑现场工况,对安全性、可靠性、稳定性要求都很高,我们现场控制级采用Profibus DP总线连接,监控操作级采用Ethernet方案,接入焦化厂局域网主服务器系统,实现远程监视。配置上:西门子S7-200配置EM277 Profibus 总线模块,S7-300选用315-2 DP,并配置CP341-1T 以太网模块,PLC集成的DP接口用于连接S7-200,以太网模块CP343-1T用于和上位机的以太网连接。
控制网络具有如下特点:良好的稳定性、扩展性、软硬件的开放性以及友好的人机界面,上位机按冗余控制配置等优点。
(系统网络图)
3.软件设计
上位机系统选用亚控公司生产的组态王软件。该软件具有友好的人机界面,支持以太网络。可以很方便的实现远程监视等功能。报表、报警功能强大,支持OPC,支持多种型号的PLC通讯。
软件设计过程中,由于上位机的程序组态王不直接支持西门子的以太网通讯协议,因此需要利用OPC Server来作为过渡。这样也使得局域网上的机器可以方便调用该机的参数,便于远程监视。
S7-300 PLC采用Step 7软件编程。软件采用模块化编程方式,把系统的各个工作编成一个个功能块,在一个OB中调用,方便易用,便于用户理解修改。支持梯形图、语句表。采用一些容错程序设计,加强系统的稳定性。
4.主要控制设计
4.1 油路冷却系统自启控制
每次鼓风机启动前先启动液压油泵,让油流入升速器中,冷却摩擦产生热量,否则鼓风机不能启动。在运行中如果主油泵压力达不到要求,辅助油泵自动启动,并能根据油温自动加热。并对油路的堵塞情况、不同点的油温检测。
4.2 鼓风机变频、工频自动切换控制
一台鼓风机变频运行,当变频器故障跳闸时,系统会自动切换工频运行,同时,小循环回流阀立即打开,机前煤气压力控制靠调节的小循环阀开度来实现。为了减小机前压力无扰动切换,小循环开度初始值设为50%。
4.3 两台鼓风机无扰动切换控制
当1#鼓风机变频运行,要停机检修变频器或风机时,投入3#鼓风机。操作先用2#变频器启动3#鼓风机,同时停 1#变频器。由于机前压力实现PID闭环控制,使得1#变频按照设定的减速时间,平滑停车,进口阀门**缓慢减小。相反,3#鼓风机按照设定加速时间,转速平滑上升,进口阀门**缓慢增加。这样保证机前集气母管压力恒定,实现两台鼓风机无扰动切换,解决原控制系统下两台鼓风机切换时产生的系统管网压力发生剧烈波动的问题。(详见系统流程图)
4.4 机前压力PID闭环控制
对于压力、**等被调参数来说,对象调节通道时间常数T0较小,而负荷又变化较快,这时微分作用和积分作用都要引起振荡,对调节质量影响很大,故不采用微分调节规律。因此,焦炉煤气压力自动调节控制、小循环阀自动调节都采用PI调节。P值越大,比例调节作用越强,I值越小,积分作用越强
4.5 压力传感器掉线控制
对于一些可靠性要求非常高的控制系统,被控对象提出多点采集的理论,因此在机前母管上取两个压力采集点。把这两点的压力值送入PLC S7-300中比较,如果差值大于某个值,就认为压力值小的传感器故障。这样保证采集压力值的准确性,从而保证系统可靠性。
4.6 紧急故障预案措施
鼓风变频控制系统在主控室设计有紧急操作箱。在控制系统瘫痪情况下,操作转换开关,通过硬连接线断开变频器上下接触器,甩开变频直接工频启动,小循环系统自动倒入原来老控制系统,以防止事故扩大。例如:Profibus总线电缆故障了,鼓风机处于失控状态,机前压力靠风机惯性缓慢减小,这时控制系统会发出声光告警,报通讯故障,需要人工迅速干预切换为老控制方式下。
4.7 两台上位机监控系统热冗余控制
两台上位机同时监控整个系统,当主上位机A故障退出时,从上位机B仍然能实时监控系统,这样保证系统的安全性、可靠性。
三、结束语
用高压变频器控制鼓风机,实现鼓风机机前集气母管的压力恒定控制,大大改善了焦炉生产及现场环境,完全达到了生产工艺要求。PLC控制技术、PROFIBUS总线技术和高压变频技术的完美结合,使得集成自动化程度高,运行稳定,操作简单,节能高效明显等优点。解决了两台鼓风机并列运行靠调节回流阀无法实现压力恒定和相互无扰动切换,这个始终困扰焦炉生产的难题。
焦炉鼓风机高压变频器控制系统的成功应用,对于改善环境、**煤气回收量和质量,都具有很高的经济价值,值得推广