JTAG相關的理論基礎
1. JTAG
-- Test Clock Input (TCK)
TCK為TAP的操作提供了一個獨立的、基本的時鐘信号,TAP的所有操作都是通過這個時鐘信号來驅動的。TCK在IEEE 1149.1标準裡是強制要求的。
-- Test Mode Selection Input (TMS)
TMS信号用來控制TAP狀态機的轉換。通過TMS信号,可以控制TAP在不同的狀态間互相轉換。TMS信号在TCK的上升沿有效。TMS在IEEE 1149.1标準裡是強制要求的。
-- Test Data Input (TDI)
TDI是資料輸入的接口。所有要輸入到特定寄存器的資料都是通過TDI接口一位一位串行輸入的(由TCK驅動)。TDI在IEEE 1149.1标準裡是強制要求的。
-- Test Data Output (TDO)
TDO是資料輸出的接口。所有要從特定的寄存器中輸出的資料都是通過TDO接口一位一位串行輸出的(由TCK驅動)。TDO在IEEE 1149.1标準裡是強制要求的。
JTAG 主要應用于:電路的邊界掃描測試和可程式設計晶片的線上系統程式設計、調試。
2. Boundary-Scan 邊界掃描
邊界掃描技術的基本思想是在靠近晶片的輸入輸出管腳上增加一個移位寄存器單元。因為這些移位寄存器單元都分布在晶片的邊界上(周圍),是以被稱為邊界掃描寄存器(Boundary-Scan Register Cell)。當晶片處于調試狀态的時候,這些邊界掃描寄存器可以将晶片和外圍的輸入輸出隔離開來。通過這些邊界掃描寄存器單元,可以實作對晶片輸入輸出信号的觀察和控制。對于晶片的輸入管腳,可以通過與之相連的邊界掃描寄存器單元把信号(資料)加載倒該管腳中去;對于晶片的輸出管腳,也可以通過與之相連的邊界掃描寄存器“捕獲”(CAPTURE)該管腳上的輸出信号。在正常的運作狀态下,這些邊界掃描寄存器對晶片來說是透明的,是以正常的運作不會受到任何影響。這樣,邊界掃描寄存器提供了一個便捷的方式用以觀測和控制所需要調試的晶片。另外,晶片輸入輸出管腳上的邊界掃描(移位)寄存器單元可以互相連接配接起來,在晶片的周圍形成一個邊界掃描鍊(Boundary-Scan Chain)。一般的晶片都會提供幾條獨立的邊界掃描鍊,用來實作完整的測試功能。邊界掃描鍊可以串行的輸入和輸出,通過相應的時鐘信号和控制信号,就可以友善的觀察和控制處在調試狀态下的晶片。
利用邊界掃描鍊可以實作對晶片的輸入輸出進行觀察和控制。下一個問題是:如何來管理和使用這些邊界掃描鍊?對邊界掃描鍊的控制主要是通過TAP (Test Access Port)Controller來完成的。
3. TAP狀态機的工作原理
在前面,我們已經簡單介紹了邊界掃描鍊,而且也了解了一般的晶片都會提供幾條邊界掃描鍊,用來實作完整的測試功能。下面,我将逐漸介紹如何實作掃描鍊的控制和通路。
在IEEE 1149.1标準裡面,寄存器被分為兩大類:資料寄存器(DR-Data Register)和指令寄存器(IR-Instruction Register)。邊界掃描鍊屬于資料寄存器中很重要的一種。邊界掃描鍊用來實作對晶片的輸入輸出的觀察和控制。而指令寄存器用來實作對資料寄存器的控制,例如:在晶片提供的所有邊界掃描鍊中,選擇一條指定的邊界掃描鍊作為目前的目标掃描鍊,并作為通路對象。下面,讓我們從TAP(Test Access Port)開始。
TAP是一個通用的端口,通過TAP可以通路晶片提供的所有資料寄存器(DR)和指令寄存器(IR)。對整個TAP的控制是通過TAP Controller來完成的。事實上,通過TAP接口,對資料寄存器(DR)進行通路的一般過程是:
1) 通過指令寄存器(IR),標明一個需要通路的資料寄存器;(所謂指令就是規定選擇哪個資料寄存器)
2) 把標明的資料寄存器連接配接到TDI和TDO之間;
3) 由TCK驅動,通過TDI,把需要的資料輸入到標明的資料寄存器當中去;同時把標明的資料寄存器中的資料通過TDO讀出來。
接下來,讓我們一起來了解一下TAP的狀态機。TAP的狀态機如圖1所示,總共有16個狀态。在圖中,每個六邊形表示一個狀态,六邊形中标有該狀态的名稱和辨別代碼。圖中的箭頭表示了TAP Controller内部所有可能的狀态轉換流程。狀态的轉換是由TMS控制的,是以在每個箭頭上有标有tms = 0 或者 tms = 1。在TCK的驅動下,從目前狀态到下一個狀态的轉換是由TMS信号決定。假設TAP Controller的目前狀态為Select-DR-Scan,在TCK的驅動下,如果TMS = 0,TAP Controller進入Capture-DR狀态;如果TMS = 1,TAP Controller進入Select-IR-Scan狀态。
這個狀态機看似很複雜,其實了解以後會發現這個狀态機其實很直接、很簡單。觀察圖1,我們可以發現,除了Test-Logic Reset和Test-Run/Idle狀态外,其他的狀态有些類似。例如Select-DR-Scan和Select-IR-Scan對應,Capture-DR和Capture-IR對應,Shift-DR和Shift-IR對應,等等。在這些對應的狀态中,DR表示Data Register,IR表示Instruction Register。記得我們前面說過嗎,寄存器分為兩大類,資料寄存器和指令寄存器。其實辨別有DR的這些狀态是用來通路資料寄存器的,而辨別有IR的這些狀态是用來通路指令寄存器的。

在較長的描述整個狀态機中的每一個狀态之前,首先讓我們來想一想:要通過邊界掃描鍊來觀察和控制晶片的輸入和輸出,需要做些什麼?如果需要捕獲晶片某個管腳上的輸出,首先需要把該管腳上的輸出裝載到邊界掃描鍊的寄存器單元裡去,然後通過TDO輸出,這樣我們就可以從TDO上得到相應管腳上的輸出信号。如果要在晶片的某個管腳上加載一個特定的信号,則首先需要通過TDI把期望的信号移位到與相應管腳相連的邊界掃描鍊的寄存器單元裡去,然後把該寄存器單元的值加載到相應的晶片管腳。下面,讓我們一起來看看每個狀态具體表示什麼意思?完成什麼功能?
Test-Logic Reset
系統上電後,TAP Controller自動進入該狀态。在該狀态下,測試部分的邏輯電路全部被禁用,以保證晶片核心邏輯電路的正常工作。在TMS上連續加5個TCK脈沖寬度的“1”信号也可以對測試邏輯電路進行複位,使得TAP Controller進入Test-Logic Reset狀态。在該狀态下,如果TMS一直保持為“1”,TAP Controller将保持在Test-Logic Reset狀态下;如果TMS由“1”變為“0”(在TCK的上升沿觸發),将使TAP Controller進入Run-Test/Idle狀态。
Run-Test/Idle
這個是TAP Controller在不同操作間的一個中間狀态。這個狀态下的動作取決于目前指令寄存器中的指令。有些指令會在該狀态下執行一定的操作,而有些指令在該狀态下不需要執行任何操作。在該狀态下,如果TMS一直保持為“0”,TAP Controller将一直保持在Run-Test/Idle狀态下;如果TMS由“0”變為“1”(在TCK的上升沿觸發),将使TAP Controller進入Select-DR-Scan狀态。
Select-DR-Scan
這是一個臨時的中間狀态。如果TMS為“0” (在TCK的上升沿觸發),TAP Controller進入Capture-DR狀态,後續的系列動作都将以資料寄存器作為操作對象;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入Select-IR-Scan狀态。
Capture-DR
當TAP Controller在這個狀态中,在TCK的上升沿,晶片輸出管腳上的信号将被“捕獲”到與之對應的資料寄存器的各個單元中去。如果TMS為“0” (在TCK的上升沿觸發),TAP Controller進入Shift-DR狀态;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入Exit1-DR狀态。
Shift-DR
在這個狀态中,由TCK驅動,每一個時鐘周期,被連接配接在TDI和TDO之間的資料寄存器将從TDI接收一位資料,同時通過TDO輸出一位資料。如果TMS 為“0” (在TCK的上升沿觸發),TAP Controller保持在Shift-DR狀态;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入到Exit1-DR狀态。假設目前的資料寄存器的長度為4。如果TMS保持為0,那在4個TCK時鐘周期後,該資料寄存器中原來的4位資料(一般是在Capture-DR狀态中捕獲的資料)将從TDO輸出來;同時該資料寄存器中的每個寄存器單元中将分别獲得從TDI輸入的4位新資料。
Update-DR
在Update-DR狀态下,由TCK上升沿驅動,資料寄存器當中的資料将被加載到相應的晶片管腳上去,用以驅動晶片。在該狀态下,如果TMS為“0”,TAP Controller将回到Run-Test/Idle狀态;如果TMS為“1”,TAP Controller将進入Select-DR-Scan狀态。
Select-IR-Scan
這是一個臨時的中間狀态。如果TMS為“0” (在TCK的上升沿觸發),TAP Controller進入Capture-IR狀态,後續的系列動作都将以指令寄存器作為操作對象;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入Test-Logic Reset狀态。
Capture-IR
當TAP Controller在這個狀态中,在TCK的上升沿,一個特定的邏輯序列将被裝載到指令寄存器中去。如果TMS為“0” (在TCK的上升沿觸發),TAP Controller進入Shift-IR狀态;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入Exit1-IR狀态。
Shift-IR
在這個狀态中,由TCK驅動,每一個時鐘周期,被連接配接在TDI和TDO之間的指令寄存器将從TDI接收一位資料,同時通過TDO輸出一位資料。如果TMS 為“0” (在TCK的上升沿觸發),TAP Controller保持在Shift-IR狀态;如果TMS為“1” (在TCK的上升沿觸發),TAP Controller進入到Exit1-IR狀态。假設指令寄存器的長度為4。如果TMS保持為0,那在4個TCK時鐘周期後,指令寄存器中原來的 4bit長的特定邏輯序列(在Capture-IR狀态中捕獲的特定邏輯序列)将從TDO輸出來,該特定的邏輯序列可以用來判斷操作是否正确;同時指令寄存器将獲得從TDI輸入的一個4bit長的新指令。
Update-IR
在這個狀态中,在Shift-IR狀态下輸入的新指令将被用來更新指令寄存器。
說了那麼多,下面,讓我們先看看指令寄存器和資料寄存器通路的一般過程,以便建立一個直覺的概念。
(1)系統上電,TAP Controller進入Test-Logic Reset狀态,然後依次進入:Run-Test/Idle ---> Select-DR-Scan ---> Select-IR-Scan ---> Capture-IR ---> Shift-IR ---> Exit1-IR ---> Update-IR,最後回到Run-Test/Idle狀态。在Capture-IR狀态中,一個特定的邏輯序列被加載到指令寄存器當中;然後進入到 Shift-IR狀态。在Shift-IR狀态下,通過TCK的驅動,可以将一條特定的指令送到指令寄存器當中去。每條指令都将确定一條相關的資料寄存器。然後從Shift-IR ---> Exit1-IR ---> Update-IR。在Update-IR狀态,剛才輸入到指令寄存器中的指令将用來更新指令寄存器。最後,進入到Run-Test/Idle狀态,指令生效,完成對指令寄存器的通路。
(2)目前可以通路的資料寄存器由指令寄存器中的目前指令決定。要通路由剛才的指令標明的資料寄存器,需要以Run-Test/Idle為起點,依次進入 Select-DR-Scan ---> Capture-DR ---> Shift-DR ---> Exit1-DR ---> Update-DR,最後回到Run-Test/Idle狀态。在這個過程當中,被目前指令標明的資料寄存器會被連接配接在TDI和TDO之間。通過TDI和 TDO,就可以将新的資料加載到資料寄存器當中去,同時,也可以捕獲資料寄存器中的資料。具體過程如下。在Capture-DR狀态中,由TCK的驅動,晶片管腳上的輸出信号會被“捕獲”到相應的邊界掃描寄存器單元中去。這樣,目前的資料寄存器當中就記錄了晶片相應管腳上的輸出信号。接下來從 Capture-DR進入到Shift-DR狀态中去。在Shift-DR狀态中,由TCK驅動,在每一個時鐘周期内,一位新的資料可以通過TDI串行輸入到資料寄存器當中去,同時,資料寄存器可以通過TDO串行輸出一位先前捕獲的資料。在經過與資料寄存器長度相同的時鐘周期後,就可以完成新信号的輸入和捕獲資料的輸出。接下來通過Exit1-DR狀态進入到Update-DR狀态。在Update-DR狀态中,資料寄存器中的新資料被加載到與資料寄存器的每個寄存器單元相連的晶片管腳上去。最後,回到Run-Test/Idle狀态,完成對資料寄存器的通路。
上面描述的就是通過TAP對資料寄存器進行通路的一般流程。會不會還是覺得很抽象?讓我們來看一個更直覺的例子。現在假設,TAP Controller現在處在Run-Test/Idle狀态,指令寄存器當中已經成功的寫入了一條新的指令,該指令標明的是一條長度為6的邊界掃描鍊。下面讓我們來看看實際如何來通路這條邊界掃描鍊。圖2所示的是測試晶片及其被目前指令標明的長度為6的邊界掃描鍊。由圖2可以看出,目前選擇的邊界掃描鍊由6個邊界掃描移位寄存器單元組成,并且被連接配接在TDI和TDO之間。TCK時鐘信号與每個邊界掃描移位寄存器單元相連。每個時鐘周期可以驅動邊界掃描鍊的資料由TDI到TDO的方向移動一位,這樣,新的資料可以通過TDI輸入一位,邊界掃描鍊的資料可以通過TDO輸出一位。經過6個時鐘周期,就可以完全更新邊界掃描鍊裡的資料,而且可以将邊界掃描鍊裡捕獲的6位資料通過TDO全部移出來。
在IEEE 1149.1标準當中,規定了一些指令寄存器、公共指令和相關的一些資料寄存器。對于特定的晶片而言,晶片廠商都一般都會在IEEE 1149.1标準的基礎上,擴充一些私有的指令和資料寄存器,以幫助在開發過程中進行進行友善的測試和調試。在這一部分,我将簡單介紹IEEE 1149.1規定的一些常用的指令及其相關的寄存器。
指令寄存器<b></b>
指令寄存器允許特定的指令被裝載到指令寄存器當中,用來選擇需要執行的測試,或者選擇需要通路的測試資料寄存器。每個支援JTAG調試的晶片必須包含一個指令寄存器。
資料寄存器
-- BYPASS指令和Bypass資料寄存器:
Bypass寄存器是一個一位的移位寄存器,通過BYPASS指令,可以将bypass寄存器連接配接到TDI和TDO之間。在不需要進行任何測試的時候,将 bypass寄存器連接配接在TDI和TDO之間,在TDI和TDO之間提供一條長度最短的串行路徑。這樣允許測試資料可以快速的通過目前的晶片送到開發闆上别的晶片上去。
-- IDCODE指令和Device Identification 資料寄存器:
Device identification寄存器中可以包括生産廠商的資訊,部件号碼,和器件的版本資訊等。使用IDCODE指令,就可以通過TAP來确定器件的這些相關資訊。例如,ARM MULTI-ICE可以自動識别目前調試的是什麼片子,其實就是通過IDCODE指令通路Device Identification寄存器來擷取的。
-- INTEST指令和Boundary-Scan 資料寄存器:
Boundary-Scan寄存器就是我們前面例子中說到的邊界掃描鍊。通過邊界掃描鍊,可以進行部件間的連通性測試。當然,更重要的是可以對測試器件的輸入輸出進行觀測和控制,以達到測試器件的内部邏輯的目的。INTEST指令是在IEEE 1149.1标準裡面定義的一條很重要的指令:結合邊界掃描鍊,該指令允許對開發闆上器件的系統邏輯進行内部測試。在ARM JTAG調試當中,這是一條頻繁使用的測試指令。
我們前面說過,寄存器分為兩大類:指令寄存器和資料寄存器。在上面提到的Bypass寄存器、Device Identification寄存器和Boundary-scan寄存器(邊界掃描鍊),都屬于資料寄存器。在調試當中,邊界掃描寄存器(邊界掃描鍊)最重要,使用的也最為頻繁。
JTAG相關的源碼分析
1. 我們可以用C語音程式來模拟以上TAP狀态機的狀态變化:
#define TEST_LOGIC_RESET 0
#define RUN_TEST_IDLE 1
#define SELECT_DR_SCAN 2
#define CAPTURE_DR 3
#define SHIFT_DR 4
#define EXIT1_DR 5
#define PAUSE_DR 6
#define EXIT2_DR 7
#define UPDATE_DR 8
#define SELECT_IR_SCAN 9
#define CAPTURE_IR 10
#define SHIFT_IR 11
#define EXIT1_IR 12
#define PAUSE_IR 13
#define EXIT2_IR 14
#define UPDATE_IR 15
Const unsight char StateTranslateTbl[16][2]=
{
{RUN_TEST_ IDLE, TEST_LOGIC_RESET },
{ RUN_TEST_ IDLE,SELECT_DR_SCAN},
{ CAPTURE_DR, SELECT_IR_SCAN },
{ SHIFT_DR, EXIT1_DR },
{ PAUSE_DR,UPDATE_DR},
{ PAUSE_DR, EXIT2_DR },
{ SHIFT_DR,UPDATE_DR},
{ IDLE, SELECT_DR_SCAN },
{ CAPTURE_IR, TEST_LOGIC_RESET },
{ SHIFT_IR, EXIT1_IR },
{ PAUSE_IR,UPDATE_IR},
{ PAUSE_IR, EXIT2_IR },
{ SHIFT_IR,UPDATE_IR},
{ RUN_TEST_ IDLE, SELECT_DR_SCAN },
}
/*************************************************
參數: TMS_Value 目前TMS的輸入值
傳回值:在目前TMS輸入作用下所産生的新的狀态值
**************************************************/
Unsigned char GetCurrentState(unsigned char TMS_Value)
Static unsight char State=RESET;
If(TMS_Value
State= StateTranslateTbl[State][ TMS_Value];
Return state;
Return 0xff;
2.TAP狀态機控制的C語音實作:
下面我們隻讨論幾個基本的操作:
(1)TAP複位操作:
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(); //理論上5個周期就可以,不過為了
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY();//可靠穩定,多一個周期也無妨
(2)TAP開始運作操作:
void JTAG_RunTestldleState( void )
JTAG_Reset();
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY(); //一個周期就可以,
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); // 為了穩定可靠可以多加
JTAG_SET(TDI_H|TMS_L|TCK_L);JTAG_DELAY();
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY();
(3)TAP寫指令操作:
void JTAG_ShiftIRState(char *wrIR)
int size;
int i;
int tdi;
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); // Select-DR-Scan
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); //Select-IR-Scan
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Capture-IR
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Shift-IR
size=strlen(wrIR);
for( i=0;i
tdi= (wrIR[i] ==HIGH) ? TDI_H:TDI_L;
JTAG_SET(tdi|TMS_L|TCK_L);JTAG_DELAY();
JTAG_SET(tdi|TMS_L|TCK_H);JTAG_DELAY(); //Shift-IR
tdi=(wrIR[i] ==HIGH) ? TDI_H:TDI_L; //i=3
JTAG_SET(tdi|TMS_H|TCK_L);JTAG_DELAY();
JTAG_SET(tdi|TMS_H|TCK_H);JTAG_DELAY(); //Exit1-IR
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); //Update-IR
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Run-Test/Idle
(4)TAP寫資料寄存器,同時也讀資料寄存器操作:
void JTAG_ShiftDRState(char *wrDR, char *rdDR)
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); //Select-DR-Scan
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Capture-DR
JTAG_SET(TDI_H|TMS_L|TCK_H);JTAG_DELAY(); //Shift-DR
size=strlen(wrDR);
for(i=0;i
tdi=(wrDR[i]==HIGH) ? TDI_H:TDI_L;
JTAG_SET(tdi|TMS_L|TCK_H);JTAG_DELAY(); //Shift-DR
rdDR[i]=JTAG_GET_TDO();
tdi=(wrDR[i]==HIGH) ? TDI_H:TDI_L; //i=S3C2410_MAX_CELL_INDEX
JTAG_SET(tdi|TMS_H|TCK_H);JTAG_DELAY(); //Exit1-DR
rdDR[i] = JTAG_GET_TDO();
JTAG_SET(TDI_H|TMS_H|TCK_H);JTAG_DELAY(); //Update-DR
(4)TAP隻寫資料寄存器操作:
void JTAG_ShiftDRStateNoTdo(char *wrDR)
所有基于JTAG的測試、程式設計和調試工具,都是遵循以上TAP狀态機的規律的。而所有工具所實作的複雜功能,細化到底層,也離不開以上幾個基本的操作。