发明名称 基于目标机上的EJTAG部件的交叉调试器实现方法
摘要 本发明提出了一种利用软件有效控制和使用目标机上的EJTAG部件的方案,据此完成了基于EJTAG的交叉调试器的设计与实现。该方案的特征在于:调试器命令的处理过程全部运行于宿主机,宿主机与目标机之间只需要4~5根信号线,不需要任何额外的硬件设备。调试器以高的性能/价格比实现了运行在宿主机上的汇编级和源码级的调试功能,并且具有良好的适应性与可移植性。
申请公布号 CN1564136A 申请公布日期 2005.01.12
申请号 CN200410009001.9 申请日期 2004.04.02
申请人 清华大学 发明人 田金兰;苏宏谋;王生原
分类号 G06F11/36 主分类号 G06F11/36
代理机构 代理人
主权项 1.基于目标机上的EJTAG部件的交叉调试器实现方法,其特征在于:调试命令的处理过程是全部在宿主PC机上运行的,它包含以下步骤:(1)使扩展了EJTAG部件的目标机MIPS CPU中的测试访问端口即Test Access Port简称TAP接口的由IEEE技术委员会联合测试行动小组Joint Test Action Group简称JTAG制定的IEEEE1149.1工业标准中的下述5个JTAG信号通过信号线与宿主机PC的并行I/O端口相连:TCK即测试时钟Test Clock信号,方向从宿主PC机到目标机MIPS CPU;TMS即测试方式选择Test Mode Select信号,方向从宿主PC机到目标机MIPS CPU;TDI即测试数据输入Test Data Input信号,方向从宿主PC机到目标机MIPS CPU;TDO即测试数据输出Test Data Output信号,方向从目标机MIPS CPU到宿主PC机;TRST*即测试复位Test Reset Input*信号,它是可选信号;(2)在宿主PC机的存储器上建立以下模块:对于运行在Windows系统下的汇编级调试器,它建有以下模块:a.人机界面模块,采用图形用户接口GUI界面,被调试目标代码的显示格式使用反汇编代码,它通过以下函数来提供操作界面:OnOpenDocument():把反汇编显示格式的代码读入内存,并设定以下变量之值:存储每行代码的长度,存储代码,当前行特征位flag,1表示为当前行,0表示非当前行,断点表,存储断点信息,0表示无断点,非0表示有断点,相应数字即断点类型,代码行特征位flag,1表示为代码行,0表示非代码行(注释等);OnDownload():下载Motorola的S-记录即S-Record格式的代码到目标机指定地址开始的存储区域;OnDraw():以不同颜色显示代码;OnEditBrk():添加断点,向接口发出断点指令;OnEditMem();得到并显示指定地址内存的内容;OnEditReg();得到并显示所有寄存器的值;OnRestart();发送重启指令,重启CPU;OnSingleStep();发送单步操作命令,并获得单步操作后寄存器的值;OnRemoveBreakPoint();移除断点;Pack():根据RSP协议,为包的内容添置包头包尾,b.调试请求处理模块,它是上层的人机界面模块和下层的EJTAG/JTAG信号转换及处理模块的应用程序API,它把人机界面的调试请求转换成为符合Remote Serial Protocol协议的数据包,发送给EJTAG/JTAG信号转换及处理模块,再接収其响应,后者设有以下9类调试命令:Callg():读所有的寄存器,简称g,CallG():写入所有的寄存器,简称G,Callm():读存储器,简称m,CallM():写存储器,简称M,CallR():复位,发出CPU中断后执行的起始地址,简称R,Callc():继续,发出清除单步标志后继续执行的起始地址,简称c,Calls():单步操作,发出开始单步执行的起始地址,简称s,Callz():插入断点,设定某一地址范围为断点,简称z,CallZ():移除断点,取消某一地址范围的断点,简称Z;相应地,调试请求处理模块设定以下各个调试请求所用到的函数:CallAPI():通过EJTAG TAP接口执行从人机界面传来的调试命令,据此调试命令分别调用由下层的EJTAG/JTAG信号转换及处理模块给出的以上9类调试命令,再返回调试结果,VerifyCommand():验证指令包是否合法,并从中提取有用部分,GetFirstChar():提取指令的第一个字符,StrFreeCpy():拷贝一个串;c.EJTAG信号转换及处理模块,它把RSP格式的调试命令请求转换为JTAG信号,使得与目标机CPU的处理过程同步,并返回响应信息,相应于上述需要处理的调试命令,它对应地设有以下接口函数:CallR():执行R指令,返回结果,Callg():执行g指令,返回结果,CallG():执行G指令,返回结果,Callm():执行m指令,返回结果,CallM():执行M指令,返回结果,Callc():执行c指令,返回结果,Calls():执行s指令,返回结果,Callz():执行z指令,返回结果,CallZ():执行Z指令,返回结果;这些接口函数的实现用到了如下函数:Pack():根据RSP协议,为包的内容添置包头包尾,SetWord():通过EJTAG TAP设置一个32位EJTAG寄存器的值,返回值为0;GetWord():通过EJTAG TAP接口取得一个32位EJTAG寄存器的值,返回寄存器的值,IsDigit():判断一个字符是否代表一个十六进制数字,是则返回值1,非则返回值,SendSignal():通过并口将信号发送到EJTAG TAP接口并接受反馈;对于运行在Linux系统下的高级语言级即原码级调试器,它的前端采用GDB,后端通过下述的EJTAG驱动程序模块与上述EJTAG/JTAG信号转换及处理模块接口:d.EJTAG驱动程序模块,实现了开始调试、结束调试、发送调试请求、读取调试响应四项功能;它与上述EJTAG/JTAG信号转换及处理模之间进行的调试命令的交换自然也是采用GDB的RSP协议格式,这使得汇编级调试器和原码级调试器共享EJTAG/JTAG信号转换及处理模块;该EJTAG驱动程序采用可装载的内核模块的方式:用insmod命令装入该模块,用rmmod命令卸载该模块;在EJTAG模块装入Linux系统以后,建立了一个设备/dev/ejtag,以符合GDB的串口调试的要求;(3)运行于Windows系统下的汇编级调试器的执行过程:a.通过函数OnOpenDocument()将反汇编格式的被调试目标代码装入内存,b.通过函数OnDraw()以不同颜色显示代码,c.若需要,通过函数OnDownload()将代码下载到目标机,d.根据需要,通过函数OnEditBrk(),OnEditMem(),OnEditReg(),OnRestart(),OnSingleStep(),OnRemoveBreakPoint()实现添加断点,得到并显示指定地址内存的内容,得到并显示所有寄存器的值,重启CPU,发送单步操作命令并获得单步操作后寄存器的值,移除断点的操作,e.通过GUI重复以上过程,或退出调试器;(4)运行于Linux系统下的高级语言级调试器的执行过程:a.用insmod命令装入EJTAG驱动程序模块,b.通过GDB命令实现需要完成的调试操作,c.重复步骤b,或退出GDB, d.用rmmod命令卸载EJTAG驱动程序模块;(5)对于运行于Windows系统下的汇编级调试器,调试请求处理模块的主函数CallAPI()对步骤(3)中遇到的调试命令的参数及调试操作构成的数据包,利用函数VerifyCommand()和GetFirstChar()对包进行校验及合法性检验,然后再根据GetFirstChar()的返回值分别调用Callxxx()所代表的EJTAG/JTAG信号转换及处理模块给出的CallR(),Callg(),CallG(),Callm(),CallM(),Callc(),Calls(),Callz(),CallZ()等函数,再返回调试结果;(6)类似地,对于运行于Linux系统下的高级语言级调试器,连接GDB的EJTAG驱动程序模块使GDB发出的调试命令分别调用EJTAG/JTAG信号转换及处理模块给出的CallR(),Callg(),CallG(),Callm(),CallM(),Callc(),Calls(),Callz(),CallZ()等函数,再返回调试结果;(7)对于运行于Windows系统下的汇编级调试器以及运行于Linux系统下的高级语言级调试器,二者共用的EJTAG/JTAG信号转换及处理模块给出CallR(),Callg(),CallG(),Callm(),CallM(),Callc(),Calls(),Callz(),CallZ()等函数的实现,实现过程用到上述包括Pack(),SetWord(),GetWord(),IsDigit(),SendSignal()的函数;(8)函数CallR()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.将EJTAG控制寄存器即ECR寄存器中的复位标志位Rocc置0,以及EJTAG中断请求位EjtabBrk,虚拟内存段dseg(debug segment)有效位ProbEn,和调试例外向量地址控制位ProbTrap皆置1;c.设置调试例外程序计数器(DEBUG Exception Program Counter)DEPC的值;d.如b,c执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;e.返回“”;(9)函数Callg()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.通过Store指令得到32个通用寄存器的数值;c.通过MFC0,Store指令得到27个cp0寄存器的数值;d.如b,c执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;e.返回通用寄存器和cp0寄存器的内容;(10)函数CallG()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.通过Load,MTC0指令设置27个cp0寄存器的数值;c.通过Load指令设置32个通用寄存器的数值;d.如b,c执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;e.返回“OK”;(11)函数Callm()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.将内存内容Load到通用寄存器;c.通过Store指令得到通用寄存器的数值;d.如b,c执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;e.返回内存内容;(12)函数CallM()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.通过Load指令得到通用寄存器的数值;c.将通用寄存器数值Store到内存中去;d.如b,c执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;e.返回“OK”;(13)函数Callc()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.清除Debug寄存器中的SSt位;c.设置调试例外程序计数器DEPC的值;d.填入DERET指令;e.调用Callg()得到寄存器内容;f.如b,c,d,e执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;g.返回结果;(14)函数Calls()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.清除Debug寄存器中的SSt位;c.设置调试例外程序计数器DEPC的值;d.填入DERET指令;e.调用Callg()得到寄存器内容;f.如b,c,d,e执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;g.返回结果;(15)函数Callz()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.断点对应的指令断点状态寄存器中的IBC域中的标志位ASIDuse置为0,BE置为1,若为数据断点,还需设置数据断点状态寄存器DBC域中的标志位BAL置为0,BLM置为1;c.设置断点对应的指令断点状态寄存器中的IBA域;d.设置断点对应的指令断点状态寄存器中的IBM域;e.如b,c,d执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;f.返回“OK”;(16)函数CallZ()的处理过程:a.检查指令格式是否正确,若不正确则返回,并置出错标志;b.断点对应的指令断点状态寄存器中的IBC域中的标志位BE置为0;c.如b执行过程出错(Rocc被置为1,处理器未处于预期的暂停状态),则返回,并置出错标志;d.返回“OK”;(17)上述(8)到(16)所述的EJTAG/JTAG信号转换及处理过程把相应的调试请求转换成为一个机器指令的序列,然后通过TAP接口一条一条地送给CPU执行,并取回结果内容,进行打包后返回;根据TAP的控制流程,在调试器命令的处理过程中,TAP寄存器的读写是在Shift-DR/Shift-IR状态进行的,数据在TCK时钟下降沿串行从TDO移出,在上升沿串行从TDI移入;在写TAP寄存器时,忽略从TDO移出的数据,新数据从TDI移入;读TAP寄存器时保存从TDO移出的数据,以供返回,同时将其再从TDI移入;(18)调试命令的完成需要与目标机CPU进行配合,其基本工作过程为:a.调试器循环检测ECR寄存器的PrAcc位,若为0,继续检测;若为1,表示处理器已经完成请求的操作而暂停,转b;b.调试器根据运行的状态,决定下一步动作:·如果是等待CPU中断,表示CPU已进入调试例外处理,等待例外处理的代码;那么把特定指令放入TAP的DATA寄存器;·如果是刚让CPU执行了load/store指令,并且操作数地址位于dseg段,那么需要提供操作数(load指令,往TAP的DATA寄存器写),或者读出数据(store指令,从TAP的DATA寄存器读);c.调试器把ECR的PrAcc位置为0,表示调试器就绪,CPU可以继续;d.转a;(19)上述(8)到(16)返回结果最终会反映到用户界面,之后调试器的运行过程如(3)、(4)所述。
地址 100084北京市北京100084-82信箱