JTAG最初是用來對芯片進行測試的,基本原理是在器件內(nèi)部定義一個TAP(Test Access Port?測試訪問口)通過專用的JTAG測試工具對進行內(nèi)部節(jié)點進行測試。JTAG測試允許多個器件通過JTAG接口串聯(lián)在一起,形成一個JTAG鏈,能實現(xiàn)對各個器件分別測試。現(xiàn)在,JTAG接口還常用于實現(xiàn)ISP(In-System Programmable?在線編程),對FLASH等器件進行編程。
JTAG編程方式是在線編程,傳統(tǒng)生產(chǎn)流程中先對芯片進行預(yù)編程實現(xiàn)再裝到板上因此而改變,簡化的流程為先固定器件到電路板上,再用JTAG編程,從而大大加快工程進度。JTAG接口可對PSD芯片內(nèi)部的所有部件進行編程
簡單地說,JTAG的工作原理可以歸結(jié)為:在器件內(nèi)部定義一個TAP(TestAccessPort,測試訪問口),通過專用的JTAG測試工具對內(nèi)部節(jié)點進行測試和調(diào)試。
邊界掃描
邊界掃描(Boundary-Scan)即在芯片的每個輸入輸出管腳上都增加一個移位寄存器單元(Boundary-Scan Register Cell),因為這些移位寄存器單元分布在芯片的邊界上,所以被稱為邊界掃描寄存器。在JTAG 調(diào)試中,邊界掃描是一個很重要的概念,當需要調(diào)試芯片時,這些寄存器將芯片與外圍電路隔離,實現(xiàn)對芯片輸入輸出信號的觀察和控制:對于輸入管腳,可以通過與之相連的邊界掃描寄存器單元把數(shù)據(jù)加載到該管腳中;對于輸出管腳,可以通過與之相連的邊界掃描寄存器“捕獲”(CAPTURE)該管腳上的輸出信號;正常運行狀態(tài)下,這些邊界掃描寄存器單元對芯片是透明的,所以正常的運行不會受到影響。另外,芯片輸入輸出管腳上的邊界掃描(移位)寄存器單元可以相互連接起來,在芯片的周圍形成一個邊界掃描鏈(Boundary-Scan Chain),它可以串行的輸入和輸出,通過相應(yīng)的時鐘信號和控制信號,實現(xiàn)對處在調(diào)試狀態(tài)下的芯片的輸入和輸出狀態(tài)的觀察和控制。
在CPU外圍,處理器內(nèi)部包含了JTAG的硬件實現(xiàn),并且向外界提供接口,也就是上面所說的TMS、TCK、TDI、TDO四個引腳。
這里的CPU:是指運算處理單元,只包含了內(nèi)部寄存器以及運算單元等基本部件。
這里的處理器:是指CPU 擴展芯片,不是SoC。
JTAG如何用于芯片測試呢? 其中用到的最主要部件就是邊界掃描鏈。命名為邊界掃描鏈,是由于它位置處于處理器的邊界上。
我們知道CPU是通過引腳與外圍交流的,所有的數(shù)據(jù)都會通過引腳輸入或者輸出,而JTAG就是通過監(jiān)控引腳的信號達到芯片測試的目的。而邊界掃描鏈就是在引腳上的一個部件。如下圖:
通過邊界掃描鏈,當有信號輸入的時候,邊界掃描鏈就能獲取信號,當CPU要輸出信號的時候,邊界掃描鏈也能獲取要輸出的信號。另外,也可以通過邊界掃描鏈來直接向外部輸出信號。
無論是信號的抓取還是輸出,都需要有接口來保存這些信號,TDI 跟 TDO 就是做這樣一些工作的。如圖:
本來邊界掃描鏈保存著引腳上的信號,當通過TDI引腳輸入我們自己的信號的時候,會發(fā)生沿上面紅線方向的移位操作,
TDI ——〉 邊界掃描鏈 —— 〉 TDO
就能從TDO獲取邊界掃描鏈上的信號,我們從TDI輸入的信號也會到邊界掃描鏈上去。
在CPU跟外界通信的引腳上的數(shù)據(jù)無非就是 指令 跟 數(shù)據(jù)信號(包括地址跟數(shù)據(jù)) 兩種。但是這兩者的結(jié)合形成了一個完整的程序,能對它們進行監(jiān)控就表明我們能進行程序的調(diào)試。一般的芯片都會提供幾條獨立的邊界掃描鏈,對邊界掃描鏈的控制主要是通過 TAP(Test Access Port) Controller來完成的。
上面的只是jtag最基本的原理,要對程序更好的調(diào)試還需要控制部件,還有更多寄存器的結(jié)合等等。
下面是一個完整的jtag調(diào)試部件:
下面來講講arm上的jtag調(diào)試,openocd就是一個jtag的調(diào)試工具
我們在調(diào)試程序的時候,通常需要設(shè)置斷點,斷點也就是指令所在的位置,
斷點分為兩種:硬件斷點跟軟件斷點
硬件斷點:指令的地址。當cpu要去某個地址取指令的時候,就暫停cpu的運行。在s3c2440上只支持兩個硬件斷點
軟件斷點:軟件斷點不限制斷點的個數(shù),因此硬件斷點的方法是不可用的。當我們需要在某個指令上打斷點的時候,openocd會先去取得斷點的地址,然后把每個斷點處的值替換成某個特定的值(如deeedeee),當cpu取數(shù)據(jù)的時候得到該特定的值,就知道到達了斷點地址,暫停cpu的運行,去除斷點的時候再把原本的值換回去。如果沒指定硬件斷點的話,一般都默認是軟件斷點。
另外openocd對于軟件斷點有特定的要求:
1.程序必須位于它的鏈接地址上,即如果指定了。 = 0x30000000,那么程序必須實際上是位于0x30000000這個地方,也就是說程序必須已經(jīng)重定位好,位于它的鏈接地址。
2.程序必須按照某種特定的順序排放:
SECTIONS{
。 = 0x30000000;
.text :{
head.o(.text)
init.o(.text)
nand.o
*(.text)
}
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : {*(.data)}
.bss ALIGN(4) : {*(.bss) *(COMMON)}
}
gdb調(diào)試就是基于軟件斷點的調(diào)試,我們可以用gdb對程序代碼的某一行進行斷點設(shè)置,那么它是如何定位到某個指令的地址的?
這就需要有調(diào)試信息,也就是在編譯的時候加上 -g 給程序添加調(diào)試信息。
eclipse對gdb進行了進一步的封裝(GUI),我們可以通過對eclipse進行某些設(shè)置達到調(diào)試arm程序的目的。
1.首先把文件加入工程
2.設(shè)置調(diào)試配置:
點工具欄上的小蟲子
Debug Configurations.。。
新建一個調(diào)試配置
選擇選項卡Main,在C/C++ Application: 選項上選擇要調(diào)試的elf文件
選擇選項卡Debugger,GDB debugger: 選擇為arm-elf-gdb
選擇選項卡Commands, ‘Initialize’conmmands 下輸入命令:
target remote 127.0.0.1:3333 //連接openocd
load //加載程序到內(nèi)存
break _start //設(shè)置斷點到_start
c //continue繼續(xù)執(zhí)行
然后Apply ,最后Debug開始調(diào)試
3.當然,上述程序是在內(nèi)存執(zhí)行的,但是開發(fā)板一開始的時候內(nèi)存還沒初始化,是不可用的,因此我們需要先設(shè)置內(nèi)存
在openocd的命令控制臺上(telnet 127.0.0.1 4444進入openocd控制臺)
halt //暫停cpu
load_image init.bin 0 //加載內(nèi)存初始化程序 init.bin 到 0 地址
resume 0 //在0地址開始運行
halt //暫停cpu
然后就可以Debug了
Debug時,當運行到斷點處的時候,我們可以看到某些寄存器或者變量的值,這些值在eclipse上顯示:
測試訪問口TAP
TAP(TestAccessPort)是一個通用的端口,通過TAP 可以訪問芯片提供的所有數(shù)據(jù)寄存器(DR)和指令寄存器(IR)。對整個TAP的控制是通過TAP控制器(TAPController)來完成的。下面先 分別介紹一下TAP的幾個接口信號及其作用。其中,前4個信號在IEEE1149.1標準里是強制要求的。
TCK:時鐘信號,為TAP的操作提供了一個獨立的、基本的時鐘信號。
TMS:模式選擇信號,用于控制TAP狀態(tài)機的轉(zhuǎn)換。
TDI:數(shù)據(jù)輸入信號。
TDO:數(shù)據(jù)輸出信號。
TRST:復(fù)位信號,可以用來對TAPController進行復(fù)位(初始化)。這個信號接口在IEEE1149.1標準里并不是強制要求的,因為通過TMS也可以對TAPController進行復(fù)位。
STCK:時鐘返回信號,在IEEE1149.1標準里非強制要求。
簡單地說,PC機對目標板的調(diào)試就是通過TAP接口完成對相關(guān)數(shù)據(jù)寄存器(DR)和指令寄存器(IR)的訪問。
系統(tǒng)上電后,TAPController 首先進入 Test-LogicReset 狀態(tài),然后依次進入Run-Test/Idle、Selcct-DR- Scan、Select-IR-Scan、Capture-IR、Shift-IR、Exitl-IR、Update-IR狀態(tài),最后回到 Run- Tcst/Idle 狀態(tài)。在此過程中,狀態(tài)的轉(zhuǎn)移都是通過TCK信號進行驅(qū)動(上升沿),通過TMS信號對TAP的狀態(tài)進行選擇轉(zhuǎn)換的。其中,
在 Capture-IR狀態(tài)下,一個特定的邏輯序列被加載到指令寄存器中;
在Shift-IR狀態(tài)下,可以將一條特定的指令送到指令寄存器中;
在 Update—IR狀態(tài)下,剛才輸入到指令寄存器中的指令將用來更新指令寄存器。
最后,系統(tǒng)又回到Run—Test/Idle狀態(tài),指令生效,完成對指令寄存器的訪問。
當系統(tǒng)又返回到Run—Test/Idle狀態(tài)后,根據(jù)前面指令寄存器的內(nèi)容選定所需要的數(shù)據(jù)寄存器,開始執(zhí)行對數(shù)據(jù)寄存器的工作。其基本原理與指令寄存器的訪問完全相同,依次為seIect—DR—Scan、Capture—DR、Shift—D、Exitl一DR、Update—DR, 最后回到 Run-Tcst/Idle 狀態(tài)。通過TDl和TDO,就可以將新的數(shù)據(jù)加載到數(shù)據(jù)寄存器中。經(jīng)過一個周期后,就可以捕獲數(shù)據(jù)寄存器中的數(shù)據(jù),完 成對與數(shù)據(jù)寄存器的每個寄存器單元相連的芯片引腳的數(shù)據(jù)更新,也完成了對數(shù)據(jù)寄存器的訪問。
Keil、IAR、DS-5、ADS開發(fā)工具軟件等都有一個公共的調(diào)試接口RDI,那么我們?nèi)绾瓮瓿?RDI -》JTAG調(diào)試協(xié)議的轉(zhuǎn)換呢?兩種做法:
在電腦上寫一個服務(wù)程序,把Keil、IAR、DS-5中的RDI命令解析成相關(guān)的JTAG協(xié)議,然后通后一個物理轉(zhuǎn)換接口(注意,這個轉(zhuǎn)換只是電氣物理層上的轉(zhuǎn)換,就像RS232那樣的作用)發(fā)送你的的目標板。H-JTAG就是這樣的。H-JTAG的硬件就僅是一個物理電平的轉(zhuǎn)換接口,所以很簡單。 而電腦中裝的H-JTAG軟件就是前面說到的服務(wù)程序,負責協(xié)議轉(zhuǎn)換的。
做一個板,用此板直接接收來自Keil、IAR、DS-5等軟件的調(diào)試命令,由此板做RDI -》 JTAG協(xié)議的轉(zhuǎn)換。然后與目標板通信,這就是JLINK、ULINK2等仿真器的工作原理。
由上可以看出,H-JTAG由于是軟件作協(xié)議轉(zhuǎn)換的,所以速度較慢,但是硬件簡單。而第二種方法的JLINK一般帶一個強勁的CPU,作硬件協(xié)議轉(zhuǎn)換,把以硬件復(fù)雜,但速度快。目前,市場上的JTAG接口仿真器有14引腳和20引腳兩種。其中,以20引腳為主流標準,但也有少數(shù)的目標板采用14引腳。經(jīng)過簡單的信號轉(zhuǎn)換后,可以將它們通用。
評論