JTAG原理和应用

摘要:

 该笔记详细记录了对IEEE1149.1定义的JTAG标准的描述和定义,工作原理以及在实际工作中的应用,尤其是自定义开发JTAG接口来实现特定的需求。
1、JTAG原理
 随着PCB和芯片封装的发展,引脚和连线间的间隙变小,不适合用探针来点击测量,同时不同芯片需要一套标准的测试方法,JTGA标准应运而生,由IEEE的联合测试行动组即Joint Test Action Group在IEEE1149.1中定义。
 JTAG就是在每个I/O引脚增加一个移位寄存器单元,正常运行是不起作用,处于测试状态时,则用来控制引脚的状态,即监视和控制芯片的输入输出信号。因为这些单位位于芯片的边界,所以叫做边界扫描单元Boundary-Scan Register Cell。
 对于芯片的输入管脚,可以通过对应的边界扫描单元中把信号加载到管脚,而对于输出管脚,则通过对应的边界扫描单元捕获芯片输出的信号。

 所有这些扫描单元串行连接起来,就形成了一个扫描链。一般芯片都会提供几条扫描链,用来实现完整的测试功能。
1.1、JTAG引脚
 对这些扫描链的管理是通过Test Access Port Controller来实现的,TAP控制器包括两种寄存器:数据寄存器DR和指令寄存器,扫描链就是数据寄存器的一种,而指令控制器用来实现对数据寄存器的控制。
 一个TAP包括如下6个连接:
 TCK 时钟,由外部提供给TAP
 TMS 测试模式选择,TAP在时钟的上升沿采样,用来驱动TAP内部状态
机的状态迁移
 TDI  测试数据输入,外部数据输入,在时钟上升沿采样,数据移位到TAP
的数据或指令寄存器
 TDO 测试数据输出,TAP把内部数据寄存器的值移位到外部
 TRST TAP复位线,没有亦可以,因为可以通过5个TMS为1来达到同样
的目的,参见TAP的状态机

 一个最简化的连接图如下:
 
1.2、JTAG概念视图
 一般来说,一个JTAG测试体系应该包含如下组件:
  1) TAP
  2) TAP Controller
  3) 一个指令寄存器IR
  4) 一组数据寄存器DR,DR必须至少包含一个旁路数据寄存器、一个边界扫描寄存器,以及可选的设备表示寄存器和其他可选的寄存器。
 指令寄存器IR和数据寄存器DR必须分开,也就是不能把DR和IR串联,但都连接到TDI和TDO,具体选择哪个由TAP Controller确定。逻辑视图如下:
 
 一个更直观的图如下:
 
1.3、TAP Controller
 TAP Controller是一个在TMS和TCK驱动下运行的有限状态机,状态转换图如下:
 
 状态机在TCK的上升沿采样TMS,根据TMS的0、1来迁移状态,一般在上升沿采样后,如果状态要迁移,则马上迁移,或者在时钟的紧接着的下降沿迁移:
 
1.4、指令寄存器IR
 指令寄存器用来选择要执行的测试动作或选择要操作的数据寄存器,或者二者兼有,有点类似汇编中的操作码。JTAG标准定义了一系列标准的指令。IR也是通过移位来装入指令的,移入的指令先锁存在IR中,然后根据TAP的状态机起作用,IEEE1149.1规定IR至少需要2BIT,也就是至少需要支持2条指令,同时当进入Capture-IR状态时,IR的最低两BIT(和TDO连接的端)的值必须为01。必须实现的4条指令如下:
1.4.1、BYPASS指令
 BYPASS指令指示是把TDO和TDI通过数据寄存器中的盘路数据寄存器连接,而不是通过扫描链寄存器连接,也就是操作不会对扫描链起作用。
1.4.2、SAMPLE指令
 SAMPLE指令指示把芯片管脚的状态装载到扫描链寄存器中
1.4.3、PRELOAD指令
 把一个值通过移位装载到扫描链寄存器中
1.4.4、EXTEST指令
 EXTEST把通过PRELOAD装载到扫描链寄存器中的值作用到芯片管脚上,从而完成对芯片外部连接电路的测试,这条指令典型的应用是用来烧写FLASH。
1.4.5、INTEST指令
 和EXTEST指令相反,这条指令把边界扫描寄存器中的内容作用到芯片管脚的内部,即等于提供芯片一个模拟的输入。
1.4.6、IDCODE指令
 IDCODE指令用来读出设备表示寄存器中的厂商、部件号码、版本等信息。JTAG调试通常都是通过这条指令来获取目标设备的类型。
1.5、数据寄存器DR
 两个必须的数据寄存器为BYPASS寄存器和扫描链寄存器,如下图所示:
 
1.5.1、BYPASS寄存器
一位寄存器,使用BYPASS指令后处于TDI和TDO之间
1.5.6、扫描链寄存器
 这个寄存器用来保存扫描的管脚状态,或者保存外部移入要作用到管脚上的信号。
1.6、基本操作
 JTAG的操作就是根据TAP Controller状态机,在TMS/TCLK的作用下,进行状态切换,进入到正确的状态后,再进行移位操作来输入输出数据。
1.6.1、写指令寄存器
 该操作序列将一条指令移动到指令寄存器(假设起始状态为Run-Test/Idle),每个TCLK的上升沿,根据TMS的值进行状态迁移
 1) TMS-1 -> Select-DR-Scan
 2) TMS-1 -> Select-IR-Scan
 3) TMS-0 -> Capture-IR,一个事先约定的序列被装载到指令寄存器
 4) TMS-0 -> Shift-IR
 5) TMS-0 循环移位,从TDI移入要执行的指令,TDO输出的是被装载约定的序列
 6) TMS-1 ->Exit-IR
 7) TMS-1 ->Update-IR,刚移入的指令装载到指令寄存器中
 8) TMS-0 ->Run-Test/Idle
 通过上面的8个状态迁移,完成一次指令的装入,同时根据指令把对应的数据寄存器连接到TDI和TDO之间(装入的指令决定了访问哪个数据寄存器,也就是把),同时状态机回到原始状态
1.6.2、读数据寄存器
 先按照1.6.1的方式写指令寄存器,确定要操作的数据寄存器。下面的例子是读边界扫描数据寄存器:
 1) TMS-1 ->Select-DR-Scan
 2) TMS-0 ->Capture-DR,根据指令寄存器的指令,不同的数据会装载到指定的数据
寄存器中,比如IDCODE指令则会将设备信息装载到设备信息寄存器中
 3) TMS-0 ->Shift-DR
 4) TMS-0 循环移位,从TDI移入占位数据,TDO输出的是数据寄存器的内容
 5) TMS-1 ->Exit-DR
 6) TMS-1 ->Update-DR,根据不同的指令有不同的动作(或无动作)
 7) TMS-0 -> Run-Test/Idle
1.6.3、加载信号到管脚外围
 即模拟芯片输出,将信号作用到芯片外部:
 1)先将EXTEST指令写指令寄存器
 2) TMS-1 ->Select-DR-Scan
 3) TMS-0 ->Capture-DR,管脚外部信号捕获到边界扫描链寄存器中
 4) TMS-0 ->Shift-DR
 5) TMS-0 将要作用的数据移位到边界扫描链寄存器中
 6) TMS-1 ->Exit-DR
 7) TMS-1 ->Update-DR,边界扫描链寄存器中的数据作用到芯片管脚的外部一侧
 8) TMS-0 -> Run-Test/Idle
1.6.4、加载信号到管脚内圈
 即模拟外部输入,将信号作用到芯片内部:
 1) 先将INTEST指令写指令寄存器
 2) TMS-1 ->Select-DR-Scan
 3) TMS-0 ->Capture-DR,管脚外部信号捕获到边界扫描链寄存器中
 4) TMS-0 ->Shift-DR
 5) TMS-0 将要作用的数据移位到边界扫描链寄存器中
 6) TMS-1 ->Exit-DR
 7) TMS-1 ->Update-DR,边界扫描链寄存器中的数据作用到芯片管脚的内部一侧
 8) TMS-0 -> Run-Test/Idle
2、JTAG接口访问ARM7的寄存器和内存
ARM7内核集成一个EmbedICE MacroCell,这个单元有自己的扫描链,用来设置断点和和插入观察点等调试功能。MacroCell可以控制ARM7是全速运行还是在调试状态下运行,他通过DBGRQ来控制ARM7进入调试状态(置高),而ARM7核心通过DBGACK信号告知外部当前是否处于调试状态,另外一个信号是BREAKPT,一个输入ARM7核心的信号,当为1时,当前的内存存取被设为断点,若当前的内存存取为取指令,则当ARM7核心的指令流水线进入指令执行阶段时被中断,系统进入调试状态,如当前的内存存取为取数据,则当前执行执行完毕后系统进入调试状态。
当ARM处于调试状态时,系统运行的时钟为内部的DCLK,而不是外部的MCLK,而DCLK的来源是JTAG的TCK,由TAP Controller根据状态机来产生,也就是说不会每个TCLK都对应到一个DCLK,这就解释了为何CPU一次执行一个流水线周期,这也是一个重要的访问前提。
ARM7有三条扫描链,其中扫描链1为32位的数据总线和1位BREAKPT,通过扫描链的32为数据总线位,可以往ARM插入数据和指令,从而实现对通用寄存器和外部内存的访问。而BREAKPT位则告诉ARM下一步骤的执行是采用MCLK和还是DCLK。(执行完成一步骤后重新回到调试状态,即事先设定的一次一个时钟周期的执行模式,通过设置EmbedICE-RT Logic控制)。
ARM7采用三级指令流水,即取指、译码、执行,一个系统执行一个阶段。在调试状态时,ARM和外部内存实际的隔开的,中间被边界扫描寄存器隔开(INTEST指令的作用)。
2.1、访问通用寄存器
 下面演示的读取寄存器R0的例子,模拟的ARM指令为STR R0, [R0],即把R0的值存储到R0为地址的内存,使用这条指令的目的是让R0的值出现在数据总线上。这条指令的执行需要两个执行周期,一是执行地址计算,二是把R0的值放在数据总线上。
 1)将INTEST指令写指令寄存器
 2) 插入指令STR R0, [R0] & BREAKPT = 0,在Update-DR阶段作用到管脚上,相当
于ARM的取指令流水阶段
 3) 插入指令MOV R0, R0 & BREAKPT = 0,ARM的指令译码流水阶段
 4) 插入指令MOV R0, R0 & BREAKPT = 0,ARM的地址计算
 5) 通过扫描链1读出出现在数据总线上的数据,即R0的值,ARM的数据输出阶段
 起始访问通用寄存器的基本方法就是使用INTEST指令,插入特定的指令,然后在指令的指定执行阶段读取数据总线(或把数据放置到数据总线),即可事先对通用寄存器的读写。
2.2、访问外部内存
 访问外部内存,需要MCLK(因为内存是在MCLK的驱动下工作的),通过设置扫描链1的BREAKPT位为1可实现。
 1) 把要访问的内存地址写入到R0 (通过2.1的方法)
 2) 插入指令LDR R1, [R0]
 3) 执行完毕后,读入R1的内容
 写内存的方法为先将地址写入R0,值写入R1,然后插入指令STR R1, [R0]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值