参考资料:
JTAG基础知识 嵌入式软件调试技术 第2章 罗克露 主编
JTAG深入理解 Test Technology Standards Committee of the IEEE Computer Society. IEEE Standard Test Access Port and Boundary-Scan Architecture. 2001
基于JTAG的ARM调试技术 ARM JTAG 调试原理 Twentyone 编写
基于JTAG的ARM进阶 ARM7TDMI Technical Reference Manual[DDI0210B].pdf ARM11TechnicalRefManual.pdf
TIPS:
1. TRST为什么是可选信号呢?
因为通过TMS也可以复位测试逻辑
2. 为什么在TMS信号上加上拉电阻?
IEEE 1149.1规定,在TMS上没有输入信号驱动的情况下,测试逻辑工作应该和在TMS上送入高电平时是一样的,这样TAP控制器将会被强制进入Test-Logic-Reset状态。
3. TDI TMS在上升沿采样,TDO在下降沿采样?
为了避免在进行测试的时候存在竞争条件。
4. JTAG调试接口由TAP控制器、指令寄存器、数据寄存器组3部分构成,而TAP控制器就是控制测试逻辑对指令(数据)寄存器进行操作的。
5. 不管TAP控制器的原始状态是什么,只要TMS保持高电平至少5个TCK上升沿的时间以上,就将使得TAP控制器进入Test-Logic-Reset状态。只要TMS为高电平,就将使控制器保持在这一状态。
6. 每个支持JTAG调试的芯片必须至少包含一个指令寄存器。对于特定的某款芯片而言,芯片生产厂商一般都会在IEEE1149.1标准的基础山扩充一些私有的指令寄存器和数据寄存器,以方便在开发过程中进行功能测试和诊断调试。
7. JTAG标准允许不同的指令共享相同的二进制编码,通过TAP控制器的当前状态来区分指令的行为。他们是OPCODE相同的不同指令,如SAMPLE和PRELOAD
8. JTAG公共指令(public)以及私有指令(private)
通过自检对元件进行测试的能力
能依靠边界扫描寄存器对板级互联进行测试的能力
9. 必须包含的共有指令:
BYPASS
SAMPLE
PRELOAD
EXTEST
IDCODE(有设备ID寄存器的情况)
10. BYPASS:二进制编码所有位都为1
其指令的目的是将BYPASS寄存器链入该元件自身的TDI和TDO之间,这样就可以使测试数据能够快速地从扫描链中通过。
11. SAMPLE:
将边界扫描寄存器串行地链入TDI和TDO之间。
12. PRELOAD:和SAMPLE类似,但是数据流的方向是反的。S是将元件核心逻辑或外部引脚上的信号状态加载到边界扫描链中,而PRELOAD指令是将边界扫描链中的数据值送入核心逻辑或外部引脚。
13. EXTEST:用于板级互联性测试。
14. 设备ID寄存器包括3部分
厂商ID,11bits压缩码
零件编号16bits编码
版本号4bits
其核心就是Test Access Port Controller(测试访问端口控制器)的内部这个有限状态机见下图:
下面这段代码来自于JFlash-S3c2410,JTAG_Reset函数的原理见TIP5,JTAG_ReadId函数对应上面这个状态机很好理解。
void JTAG_Reset(void) { JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); }
void JTAG_ReadId(void) { int i; char id[32]; U32 id32;
JTAG_Reset();
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); // Why 4 times? JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle Status JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle Status JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle Status JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle Status
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Select-DR Scan Status
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Select-IR Scan Status
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Capture-IR Status
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Shift-IR Status
//S3C2410 IDCODE Instruction "1110" JTAG_SET(TDI_L|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_L|TMS_L|TCK_H);JTAG_DELAY(); // '0'
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // '1'
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // '1'
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // '1', //Exit1-IR
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Update_IR
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Select-DR-Scan
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Capture-DR
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Shift-DR
// Read IDcode.. for( i=0 ; i<=30 ; i++) { JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Shift-DR id[i]=(char)JTAG_GET_TDO(); }
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); //Exit1_DR id[i]=(char)JTAG_GET_TDO();
JTAG_SET(TDI_H|TMS_H|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Update_DR
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); // Why 3 times? JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // Run-Test/Idle
id32=0; for(i=31 ;i>=0 ;i--) { if(id[i]==HIGH) id32|=(1<<i); }
switch(id32) { case 0x0032409d: //S3C2410X is detected. printf("> S3C2410X(ID=0x%08x) is detected./n",id32); break; default: printf("ERROR: No CPU is detected(ID=0x%08x)./n",id32); break; } } |