1、JTAG是什么?
JTAG是20世紀(jì)80年代開(kāi)發(fā)的IEEE標(biāo)準(zhǔn)(1149.1),用來(lái)解決電路板的生產(chǎn)制造檢修問(wèn)題。
現(xiàn)在JTAG還可以用來(lái)燒程序、調(diào)試以及檢測(cè)端口狀態(tài)。本文主要介紹JTAG的基本功能,邊界掃描。
JTAG是20世紀(jì)80年代開(kāi)發(fā)的IEEE標(biāo)準(zhǔn)(1149.1),用來(lái)解決電路板的生產(chǎn)制造檢修問(wèn)題。
現(xiàn)在JTAG還可以用來(lái)燒程序、調(diào)試以及檢測(cè)端口狀態(tài)。本文主要介紹JTAG的基本功能,邊界掃描。
1.1邊界掃描
如圖1所示,在一個(gè)電路板上有兩個(gè)芯片元件,一個(gè)CPU和FPGA。

圖1
每個(gè)芯片都會(huì)有很多引腳,那么芯片之間的互聯(lián)就會(huì)有很多連線,圖2示意圖僅僅畫了4條連接線。

圖2
正常情況下,對(duì)于芯片廠商,一次制作成千上萬(wàn)個(gè)PCB板子,每個(gè)班子上都有許許多多連接線,廠家需要如何保證每根芯片連接線都是正常的呢?
這么大的工作量也不可能通過(guò)手工來(lái)每一根線進(jìn)行檢測(cè)。因此JTAG就應(yīng)運(yùn)而生了。

圖3
JTAG可以控制芯片的每個(gè)引腳,圖3中,我們可以通過(guò)JTAG使得所有的CPU引腳發(fā)送數(shù)據(jù),而所有的FPGA引腳接收數(shù)據(jù),然后根據(jù)FPGA中是否收到準(zhǔn)確的數(shù)據(jù)來(lái)判斷所有的芯片連接是否正常。
實(shí)際上JTAG的連接包括4根信號(hào)線,分別是TDI、TDO、TMS和TCK。從電腦主機(jī)的角度來(lái)看,TDI、TMS、TCK為輸出,TDO為輸入,如果從待測(cè)試的芯片角度來(lái)看則相反。

圖4
JTAG的四根信號(hào)線有特定的連接方式,如圖5所示,TMS和TCK是并聯(lián)在所有待測(cè)芯片上的。

圖5
TDI和TDO信號(hào)線則是串聯(lián)在一起形成一個(gè)閉環(huán)鏈條。在JTAG的技術(shù)手冊(cè)中,這種方式也叫JTAG鏈。

圖6
因此,每個(gè)JTAG鏈上的芯片都會(huì)有四根線連接,其中三個(gè)輸入,一個(gè)輸出。在技術(shù)手冊(cè)中,還會(huì)有一個(gè)可選的信號(hào)線TRST作為第五根信號(hào)線。一般而言,JTAG的四個(gè)引腳都是專用引腳。
現(xiàn)在所有的JTAG應(yīng)用越來(lái)越普遍,基本上所有多引腳的芯片都會(huì)包含JTAG邊界掃描功能。此外正如我們開(kāi)頭所說(shuō),CPU和FPGA廠商還用JTAG接口進(jìn)行調(diào)試,對(duì)于可編程硬件FPGA和CPLD,還可以用JTAG接口繼續(xù)配置和燒錄程序。
2、JTAG如何起作用?
上一章我們知道了JTAG是如何連接芯片,現(xiàn)在學(xué)習(xí)具體工作原理以及如何通過(guò)PC端來(lái)控制器運(yùn)行。
2.1 PC控制JTAG
一般我們用JTAG連接線來(lái)連接PC和JTAG端口,電腦端口有并行端口(也叫打印機(jī)端口db25)、USB端口以及網(wǎng)線端口。對(duì)于數(shù)據(jù)量不大的情況下推薦并行端口,操作簡(jiǎn)單。對(duì)于大數(shù)據(jù)量推薦USB端口和網(wǎng)口,其速度快但是操作復(fù)雜一些。
2.2 并行端口
電腦主機(jī)的并行端口12根線為輸出,5根線為輸入。對(duì)于JTAG而言,只用到了3個(gè)輸出和一個(gè)輸入(從PC角度來(lái)看輸入輸出)。因此,中間需要用到一些緩存器,如賽靈思的parallel-III cable。
從軟件代碼的角度來(lái)看,并行端口由于簡(jiǎn)單是最理想的JTAG端口。例如,阿爾特拉的ByteBlaster JTAG接口用C語(yǔ)言改變TCK信號(hào)代碼如下:
#define lpt_addr 0x378
#define TCK 0x01
void toggle_TCK()
{
outport(lpt_addr, 0);
outport(lpt_addr, TCK);
outport(lpt_addr, 0);
}
2.3 JTAG TAP控制器
PC和芯片之間的JTAG連接方式如圖6,下面介紹這四根信號(hào)線分別代表什么意思。
TCKTCK是JTAG的時(shí)鐘信號(hào),另外三個(gè)信號(hào)TDI、TDO、TMS都是跟該時(shí)鐘信號(hào)同步的。一般其他三根信號(hào)都是在TCK時(shí)鐘的上升沿發(fā)生改變或者狀態(tài)的切換。
TMS在每個(gè)芯片的內(nèi)部都有JTAG TAP控制器,圖6中有兩個(gè)CPU和FPGA兩個(gè)芯片,那么就有兩個(gè)TAP控制器。
一般我們?cè)跀?shù)據(jù)手冊(cè)上看到的狀態(tài)控制器就是這個(gè),它有16個(gè)狀態(tài),如圖8所示。TMS就是個(gè)控制TAP控制器的信號(hào),根據(jù)TMS的高低電平變化,TAP控制器進(jìn)入這16個(gè)狀態(tài)中的一種,又因?yàn)橥粋€(gè)PCB板子上TMS是并聯(lián)所有芯片 ,因此所有芯片都會(huì)處于同一狀態(tài)。

圖8
上圖中每個(gè)狀態(tài)旁邊的0和1代表的是TMS的低、高電平。
比如如果TAP狀態(tài)控制器處于Select DR-Scan狀態(tài),且TMS為0,那么當(dāng)TCK時(shí)鐘信號(hào)切換時(shí),TAP的狀態(tài)就會(huì)變化下面的Capture-DR。
這里再?gòu)?qiáng)調(diào)一遍,要想JTAG正常工作,所有的鏈上的TAP控制器必須處于同一狀態(tài)。
PCB板上電后,是如何保證所有芯片的TAP處于同一狀態(tài)呢?
仔細(xì)觀察圖8,不管TAP在哪個(gè)狀態(tài),如果TMS在5個(gè)時(shí)鐘周期內(nèi)都保持1,那么TAP都會(huì)變成Test-Logic-Reset狀態(tài),這便是用來(lái)同步TAP狀態(tài)的方法。
來(lái)看下面的代碼,如何將TAP控制器切換到Shift-IR狀態(tài)。
// first sync everybody to the test-logic-reset state
for(i=0; i<5; i++) JTAG_clock(TMS);
// now that everybody is in a known and identical state, we can move together to another state
// let's go to Shift-IR
JTAG_clock(0);
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
TDI和TDO現(xiàn)在我們已經(jīng)知道了如何切換TAP狀態(tài)了,下面介紹JTAG最重要的兩個(gè)狀態(tài)Shift-DR和Shift-IR。

圖9
Shift-DR和Shift-IR必須結(jié)合TDI和TDO信號(hào)線才能起作用,首先介紹Shift-DR。
每個(gè)芯片的TAP控制器中都有一個(gè)IR寄存器,也叫做指令寄存器。你可以把相關(guān)指令寫入這個(gè)寄存器,然后TAP控制器會(huì)根據(jù)IR寄存器的指令進(jìn)行相關(guān)操作。
每個(gè)IR寄存器都有一定的長(zhǎng)度,我們假設(shè)CPU的IR寄存器是5位,F(xiàn)PGA的寄存器是10位,那么通過(guò)TDI和TDO的信號(hào)線連接方式,CPU和FPGA的IR寄存器其實(shí)是串聯(lián)的,如圖10所示。

圖10
我們從PC主機(jī)的角度來(lái)看,整個(gè)鏈的IR寄存器是15位的,5位CPU和10位FPGA。
要想將IR寄存器寫入數(shù)據(jù),我們需要將TAP控制器的狀態(tài)切換成Shift-IR,然后PC通過(guò)TDI信號(hào)線寫入15位數(shù)據(jù)。前10位數(shù)據(jù)寫入的是FPGA的IR寄存器,后5位數(shù)據(jù)寫入的是CPU的IR寄存器。
如果PC寫入的數(shù)據(jù)多于15位,那么溢出的數(shù)據(jù)就會(huì)通過(guò)TDO信號(hào)線再被PC端給接收,只不過(guò)延時(shí)了15個(gè)時(shí)鐘周期。
例如,我們想吧數(shù)值00100寫入CPU的IR寄存器,而0000000010寫入FPGA的IR寄存器,C語(yǔ)言代碼如下:
// Because the bits are shifted through in a chain, we must start sending the data for the device that is at the end of the chain
// so we send the 10 FPGA IR bits first
JTAG_clock(0);
JTAG_clock(1);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
// then send the 5 CPU IR bits
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(1);
JTAG_clock(0);
JTAG_clock(0 | TMS); // last bit needs to have TMS active (to exit shift-IR)
在我們的假設(shè)中,CPU的IR是5位(可以表示數(shù)值0~31)。
那么CPU的IR寄存器可以支持32條JTAG指令。實(shí)際上,一個(gè)CPU可能只會(huì)有5~10條指令,剩下的IR寄存器數(shù)值都沒(méi)有用。
同樣的對(duì)于FPGA,它的IR寄存器是10位,那么它可以支持1024條JTAG指令(大部分也是沒(méi)用的)。
但是JTAG有幾條強(qiáng)制的指令必須都有:
BYPASSEXTESTSAMPLE/PRELOADIDCODE(這個(gè)不是強(qiáng)制的,但是非常常見(jiàn))每個(gè)芯片的都有IR數(shù)值的指令集,從芯片手冊(cè)上都可以查到。
每個(gè)芯片的TAP控制器都只有一個(gè)IR寄存器,但是會(huì)有很多DR寄存器。我們知道IR寄存器數(shù)據(jù)切換是通過(guò)TAP的Shift-IR狀態(tài),類似的,DR寄存器的數(shù)據(jù)切換也是這樣,只不過(guò)狀態(tài)是TAP的Shift-DR狀態(tài)。
每一個(gè)IR寄存器的數(shù)值都會(huì)對(duì)應(yīng)一個(gè)不同的DR寄存器,在我們的假設(shè)中IR寄存器為5位,那么就有32個(gè)IR數(shù)值,因此就有32個(gè)DR寄存器(如果32個(gè)IR數(shù)值都被當(dāng)做指令的話)。
2.4 計(jì)算JTAG鏈中元件個(gè)數(shù)
IR寄存器的指令不同芯片有所區(qū)別,但是有一個(gè)指令是一樣的,那就是BYPASS指令。
它的IR寄存器所有位都是1。對(duì)于CPU是11111,對(duì)于FPGA的IR寄存器,其數(shù)值是1111111111。
在BYPASS指令模式下,TAP控制器對(duì)應(yīng)的DR寄存器是個(gè)單觸發(fā)器,只是將TDI的輸入數(shù)據(jù)延時(shí)一個(gè)時(shí)鐘周期然后通過(guò)TDO輸出。
根據(jù)這個(gè)特性,我們可以用BYPASS指令來(lái)計(jì)算JTAG鏈上有多少個(gè)芯片。
在此指令下,每個(gè)芯片的DR寄存器會(huì)延時(shí)一個(gè)時(shí)鐘周期,那么我們發(fā)送一個(gè)數(shù)據(jù)后,檢查延時(shí)多少周期收到數(shù)據(jù),即可知道JTAG鏈上芯片的數(shù)量。
具體實(shí)現(xiàn)的C語(yǔ)言代碼如下:
// go to reset state
for(i=0; i<5; i++) JTAG_clock(TMS);
// go to Shift-IR
JTAG_clock(0);
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// Send plenty of ones into the IR registers
// That makes sure all devices are in BYPASS!
for(i=0; i<999; i++) JTAG_clock(1);
JTAG_clock(1 | TMS); // last bit needs to have TMS active, to exit shift-IR
// we are in Exit1-IR, go to Shift-DR
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// Send plenty of zeros into the DR registers to flush them
for(i=0; i<1000; i++) JTAG_clock(0);
// now send ones until we receive one back
for(i=0; i<1000; i++) if(JTAG_clock(1)) break;
nbDevices = i;
printf("There are %d device(s) in the JTAG chain\n", nbDevices);
// 將JTAG鏈置于復(fù)位狀態(tài)
// 根據(jù)JTAG標(biāo)準(zhǔn),通過(guò)一系列TMS信號(hào)(通常是特定的序列)將JTAG接口置于復(fù)位狀態(tài)
// 這里簡(jiǎn)單地假設(shè)連續(xù)5個(gè)TMS時(shí)鐘信號(hào)足以實(shí)現(xiàn)復(fù)位
for(i=0; i<5; i++) JTAG_clock(TMS);
// 從復(fù)位狀態(tài)轉(zhuǎn)移到Shift-IR狀態(tài)
// Shift-IR狀態(tài)允許數(shù)據(jù)被移入到JTAG鏈上每個(gè)設(shè)備的指令寄存器(IR)中
// 這里的序列是JTAG標(biāo)準(zhǔn)定義的一部分,用于進(jìn)入Shift-IR狀態(tài)
JTAG_clock(0);
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// 向IR寄存器發(fā)送多個(gè)1
// 因?yàn)锽YPASS指令在大多數(shù)JTAG設(shè)備中是通過(guò)在IR寄存器中設(shè)置全1來(lái)實(shí)現(xiàn)的
// 所以這里通過(guò)發(fā)送999個(gè)1(實(shí)際上只需要足夠多的1以確保所有設(shè)備都接收到BYPASS指令)
// 來(lái)確保所有設(shè)備都進(jìn)入BYPASS模式
for(i=0; i<999; i++) JTAG_clock(1);
JTAG_clock(1 | TMS); // 發(fā)送最后一個(gè)1時(shí),同時(shí)激活TMS以退出Shift-IR狀態(tài)
// 從Exit1-IR狀態(tài)轉(zhuǎn)移到Shift-DR狀態(tài)
// Shift-DR狀態(tài)允許數(shù)據(jù)被移入到JTAG鏈上每個(gè)設(shè)備的數(shù)據(jù)寄存器(DR)中
// 同樣,這里的序列是JTAG標(biāo)準(zhǔn)定義的一部分
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// 發(fā)送多個(gè)0到DR寄存器以清空它們
// 在進(jìn)入測(cè)量模式前,先通過(guò)發(fā)送一系列0來(lái)清空DR寄存器中的任何殘留數(shù)據(jù)
for(i=0; i<1000; i++) JTAG_clock(0);
// 現(xiàn)在發(fā)送1,直到接收到返回的1
// 在BYPASS模式下,DR寄存器被簡(jiǎn)化為一個(gè)單觸發(fā)器,它會(huì)將TDI的輸入延時(shí)一個(gè)時(shí)鐘周期后輸出到TDO
// 通過(guò)發(fā)送一系列1并檢查TDO輸出,我們可以測(cè)量從發(fā)送到接收的延時(shí),從而計(jì)算出JTAG鏈上的設(shè)備數(shù)量
// 當(dāng)TDO返回1時(shí),循環(huán)結(jié)束
for(i=0; i<1000; i++) if(JTAG_clock(1)) break;
// i的值現(xiàn)在等于JTAG鏈上設(shè)備的數(shù)量(加1,因?yàn)榘òl(fā)送的那個(gè)時(shí)鐘周期)
// 但由于我們是在尋找TDO返回1的時(shí)鐘周期,所以實(shí)際的設(shè)備數(shù)量應(yīng)該是i
nbDevices = i;
// 打印JTAG鏈上的設(shè)備數(shù)量
printf("There are %d device(s) in the JTAG chain\n", nbDevices);
啰嗦解釋一下:
由于BYPASS模式下,每個(gè)設(shè)備都會(huì)將輸入數(shù)據(jù)延時(shí)一個(gè)時(shí)鐘周期后輸出,因此,我們可以通過(guò)發(fā)送一個(gè)數(shù)據(jù)位,并測(cè)量從發(fā)送到接收到該數(shù)據(jù)位的時(shí)間(即時(shí)鐘周期數(shù)),來(lái)推斷JTAG鏈上設(shè)備的數(shù)量。具體做法如下:
初始化JTAG鏈:首先,通過(guò)一系列TMS信號(hào)將JTAG鏈置于復(fù)位狀態(tài),然后切換到Shift-IR狀態(tài),向每個(gè)設(shè)備的IR寄存器發(fā)送全1(即BYPASS指令),最后將JTAG鏈切換到Shift-DR狀態(tài)。清空DR寄存器:在發(fā)送BYPASS指令后,通過(guò)向DR寄存器發(fā)送一系列0來(lái)清空可能存在的舊數(shù)據(jù)。發(fā)送并接收數(shù)據(jù):向TDI發(fā)送一個(gè)1,然后逐個(gè)時(shí)鐘周期地檢查TDO輸出。由于每個(gè)設(shè)備都會(huì)將輸入延時(shí)一個(gè)時(shí)鐘周期,所以TDO將在(設(shè)備數(shù)量+1)個(gè)時(shí)鐘周期后輸出1(加1是因?yàn)榘òl(fā)送數(shù)據(jù)的那個(gè)時(shí)鐘周期)。計(jì)算設(shè)備數(shù)量:通過(guò)記錄從發(fā)送數(shù)據(jù)到接收到數(shù)據(jù)所經(jīng)過(guò)的時(shí)鐘周期數(shù),減去1(發(fā)送數(shù)據(jù)的那個(gè)周期),即可得到JTAG鏈上的設(shè)備數(shù)量。C程序它首先通過(guò)一系列TMS信號(hào)將JTAG鏈置于正確的狀態(tài),然后發(fā)送BYPASS指令到每個(gè)設(shè)備的IR寄存器,并清空DR寄存器。最后,通過(guò)發(fā)送一系列1到TDI并檢查TDO的輸出來(lái)計(jì)算設(shè)備數(shù)量。當(dāng)TDO輸出1時(shí),循環(huán)結(jié)束,此時(shí)循環(huán)的迭代次數(shù)(減去1)即為JTAG鏈上的設(shè)備數(shù)量。
2.5 獲得JTAG鏈上芯片的ID
大部分的芯片JTAG模塊都支持IDCODE指令**,這個(gè)指令對(duì)應(yīng)的DR寄存器是32位,具體數(shù)值代表者不同芯片的ID。**
不同于BYPASS指令,INCODE指令的IR寄存器數(shù)值不是標(biāo)準(zhǔn)的,我們可以通過(guò)器件手冊(cè)來(lái)查詢。
還有一種方法,當(dāng)TAP控制器的狀態(tài)處于Test-Logic-Reset時(shí),它都會(huì)將INCODE數(shù)據(jù)寫入DR寄存器中,我們可以據(jù)此讀出DR寄存器的內(nèi)容,C語(yǔ)言代碼如下:
// go to reset state (that loads IDCODE into IR of all the devices)
for(i=0; i<5; i++) JTAG_clock(TMS);
// go to Shift-DR
JTAG_clock(0);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// and read the IDCODES
for(i=0; i < nbDevices; i++)
{
printf("IDCODE for device %d is %08X\n", i+1, JTAG_read(32));
}
3、邊界掃描
本章節(jié)講解JTAG的邊界掃描。
當(dāng)TAP控制器進(jìn)入“boundary-scan”的狀態(tài),其實(shí)也就是IR寄存器存入SAMPLE指令、EXTEST指令等,此時(shí)對(duì)應(yīng)的DR寄存器就是邊界掃描寄存器,這個(gè)寄存器將每個(gè)I/O單元連接在一起并且可以控制每個(gè)引腳。

圖11
當(dāng)芯片正常過(guò)程當(dāng)中也是可以進(jìn)行邊界掃描的,例如對(duì)正常運(yùn)行中的FPGA進(jìn)行邊界掃描,它可以將每個(gè)管腳的狀態(tài)顯示出來(lái)。
3.1、SAMPLE
現(xiàn)在我們嘗試讀取管腳的值,對(duì)應(yīng)的IR寄存器的指令是SAMPLE。每個(gè)芯片的具體指令數(shù)值不同,查找數(shù)據(jù)手冊(cè)或者芯片的BSDL文件來(lái)獲取具體的指令。
BSDL全稱是boundary scan description language,它是硬件描述語(yǔ)言(VHDL)的一個(gè)子集。
一個(gè)BSDL文件其實(shí)就是一個(gè)描述邊界鏈的VHDL文件。下面是阿爾特拉的BSDL文件(Cyclone EP1C3 in TQFP 100 pins package):
attribute INSTRUCTION_LENGTH of EP1C3T100 : entity is 10;
attribute INSTRUCTION_OPCODE of EP1C3T100 : entity is
"BYPASS (1111111111), "&
"EXTEST (0000000000), "&
"SAMPLE (0000000101), "&
"IDCODE (0000000110), "&
"USERCODE (0000000111), "&
"CLAMP (0000001010), "&
"HIGHZ (0000001011), "&
"CONFIG_IO (0000001101)";
attribute INSTRUCTION_CAPTURE of EP1C3T100 : entity is "0101010101";
attribute IDCODE_REGISTER of EP1C3T100 : entity is
"0000"& --4-bit Version
"0010000010000001"& --16-bit Part Number (hex 2081)
"00001101110"& --11-bit Manufacturer's Identity
"1"; --Mandatory LSB
attribute BOUNDARY_LENGTH of EP1C3T100 : entity is 339;
從上面這個(gè)文件我們可以知道:
IR寄存器的長(zhǎng)度是10位;IR指令寄存器的指令清單,比如SAMPLE的是0000000101,也就是0x005;該器件的IDCODE,00001101110是廠商的代號(hào)(阿爾特拉);邊界掃描鏈的長(zhǎng)度是339位。邊界掃描寄存器有339位,并不意味著有339個(gè)管腳。每一個(gè)管腳都有一個(gè)IO pad(芯片管腳處理模塊),IO pad用1~3位寄存器(取決于該管腳是輸入、三態(tài)輸出或是輸入輸出均可)。
當(dāng)然一些IO pad包含的寄存器不一定包含在邊界掃描鏈中。這就解釋了為什么這個(gè)100管腳的芯片有339位的邊界掃描寄存器。
接著看BSDL文件:
attribute BOUNDARY_REGISTER of EP1C3T100 : entity is
--BSC group 0 for I/O pin 100
"0 (BC_1, IO100, input, X)," &
"1 (BC_1, *, control, 1)," &
"2 (BC_1, IO100, output3, X, 1, 1, Z)," &
--BSC group 1 for I/O pin 99
"3 (BC_1, IO99, input, X)," &
"4 (BC_1, *, control, 1)," &
"5 (BC_1, IO99, output3, X, 4, 1, Z)," &
...
...
...
--BSC group 112 for I/O pin 1
"336 (BC_1, IO1, input, X)," &
"337 (BC_1, *, control, 1)," &
"338 (BC_1, IO1, output3, X, 337, 1, Z)" ;
這一段羅列了邊界掃描寄存器的339位的用途。
例如,處于第4位(其實(shí)是位3,從0開(kāi)始計(jì)算的)保存的是管腳99的值。
現(xiàn)在讀取邊界掃描寄存器,并且將管腳99的值打印出來(lái):
// go to reset state
for(i=0; i<5; i++) JTAG_clock(TMS);
// go to Shift-IR
JTAG_clock(0);
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// Assuming that IR is 10 bits long,
// that there is only one device in the chain,
// and that SAMPLE code = 0000000101b
JTAG_clock(1);
JTAG_clock(0);
JTAG_clock(1);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0);
JTAG_clock(0 or TMS); // last bit needs to have TMS active, to exit shift-IR
// we are in Exit1-IR, go to Shift-DR
JTAG_clock(TMS);
JTAG_clock(TMS);
JTAG_clock(0);
JTAG_clock(0);
// read the boundary-scan chain bits in an array called BSB
JTAG_read(BSB, 339);
printf("Status of pin 99 = %d\n, BSB[3]);
3.2、邊界掃描寄存器
下圖是阿爾特拉數(shù)據(jù)手冊(cè)中TAP狀態(tài)寄存器、IR寄存器、DR寄存器結(jié)構(gòu)圖,各層級(jí)關(guān)系比較一目了然。
我們可以得出以下信息:
IR指令寄存器(Instruction Register)的值決定采用什么指令以及選擇對(duì)應(yīng)的DR寄存器(Data Register);Bypass Register只有一位,其指令BYPASS我們上文已經(jīng)講過(guò),其提供從TDI到TDO最短路徑;邊界掃描寄存器是個(gè)移位寄存器,由芯片上所有的管腳BSC組成。阿爾特拉的BSC全稱是Booundary scan cell,它可以將信號(hào)施加到管腳,或者獲得管腳上的數(shù)據(jù)和內(nèi)部邏輯信號(hào)。我們JTAG測(cè)試的數(shù)據(jù)也是串行輸入到BSC單元中,捕獲到的數(shù)據(jù)也是串行從BSC輸出,進(jìn)而判斷測(cè)試結(jié)果。根據(jù)我的理解,此處的BSC就是我們上文提到的IO pad芯片管腳處理模塊。3.3、JTAG還可以做什么?
控制芯片的引腳狀態(tài),對(duì)應(yīng)的IR指令為EXTEST,表示外部測(cè)試,可以讓輸出管腳輸出高低邏輯電平,根據(jù)輸入接受到的電平信號(hào)檢測(cè)JTAG鏈中任何設(shè)備管腳處的開(kāi)路和短路情況;用于FPGA和CPLD的配置;JTAG接口可以作為調(diào)試端口。怎么樣,通過(guò)本文的講解是不是對(duì)JTAG有了基本的認(rèn)識(shí)。