JTAG(Joint Test Action Group)聯合測試行動小組)是一種國際標准測試協議(IEEE 1149.1兼容),主要用於芯片內部測試。現在多數的高級器件都支持JTAG協議,如DSP、FPGA器件等。標准的JTAG接口是4線:TMS、 TCK、TDI、TDO,分別為模式選擇、時鍾、數據輸入和數據輸出線。JTAG最初是用來對芯片進行測試的,基本原理是在器件內部定義一個TAP(Test Access Port?測試訪問口)通過專用的JTAG測試工具對進行內部節點進行測試。JTAG測試允許多個器件通過JTAG接口串聯在一起,形成一個JTAG鏈,能實現對各個器件分別測試。現在,JTAG接口還常用於實現ISP(In-System Programmable?在線編程),對FLASH等器件進行編程。JTAG編程方式是在線編程,傳統生產流程中先對芯片進行預編程實現再裝到板上因此而改變,簡化的流程為先固定器件到電路板上,再用JTAG編程,從而大大加快工程進度。JTAG接口可對PSD芯片內部的所有部件進行編程
上面的信息是從度娘百科引用過來的,對於jtag沒有了解過的人來說,上面的大部分內容都不知道說什么,當然,我是一開始看的時候也看不懂。
不過從上面得出來的信息知道,jtag是一個協議,標准有4個引腳,用於芯片的測試與編程調試。
jtag是有硬件實現的。
在cpu(注意:這里的cpu是指運算處理單元,只包含了內部寄存器以及運算單元等基本部件)外圍,處理器(即cpu擴展芯片,不是soc)內部包含了jtag的硬件實現,並且向外界提供接口,也就是上面所說的TMS,TCK,TDI,TDO,四個引腳。
如圖:
邊界掃描鏈
jtag如何用於芯片測試呢? 其中用到的最主要部件就是邊界掃描鏈。
命名為邊界掃描鏈,是由於它位置處於處理器的邊界上。
我們知道cpu是通過引腳與外圍交流的,所有的數據都會通過引腳輸入或者輸出,而jtag就是通過監控引腳的信號達到芯片測試的目的。
而邊界掃描鏈就是在引腳上的一個部件。如下圖:
通過邊界掃描鏈,當有信號輸入的時候,邊界掃描鏈就能獲取信號,當cpu要輸出信號的時候,邊界掃描鏈也能獲取要輸出的信號。
另外也可以通過邊界掃描鏈來直接向外部輸出信號。
無論是信號的抓取還是輸出,都需要有接口來保存這些信號,TDI跟TDO就是做這樣一些工作的。
如圖:
本來邊界掃描鏈保存着引腳上的信號,當通過TDI引腳輸入我們自己的信號的時候,會發生沿上面紅線方向的移位操作,
TDI ——〉 邊界掃描鏈 —— 〉 TDO
就能從TDO獲取邊界掃描鏈上的信號,我們從TDI輸入的信號也會到邊界掃描鏈上去。
在cpu跟外界通信的引腳上的數據無非就是 指令 跟 數據信號(包括地址跟數據) 兩種。但是這兩者的結合形成了一個完整的程序,能對它們進行監控就表明我們能進行程序的調試。
上面的只是jtag最基本的原理,要對程序更好的調試還需要控制部件,還有更多寄存器的結合等等。
下面是一個完整的jtag調試部件:
更詳細的jtag信息可以看看http://www.micetek.com.cn/technic/jtag.pdf
下面來講講arm上的jtag調試,openocd就是一個jtag的調試工具
以下基於s3c2440,openocd
我們在調試程序的時候,通常需要設置斷點,斷點也就是指令所在的位置,
斷點分為兩種:硬件斷點跟軟件斷點
硬件斷點:指令的地址。當cpu要去某個地址取指令的時候,就暫停cpu的運行。在s3c2440上只支持兩個硬件斷點
軟件斷點:軟件斷點不限制斷點的個數,因此硬件斷點的方法是不可用的。當我們需要在某個指令上打斷點的時候,openocd會先去取得斷點的地址,然后把每個斷點處的值替換成某個特定的值(如deeedeee),當cpu取數據的時候得到該特定的值,就知道到達了斷點地址,暫停cpu的運行,去除斷點的時候再把原本的值換回去。如果沒指定硬件斷點的話,一般都默認是軟件斷點。
另外openocd對於軟件斷點有特定的要求:
1.程序必須位於它的鏈接地址上,即如果指定了. = 0x30000000,那么程序必須實際上是位於0x30000000這個地方,也就是說程序必須已經重定位好,位於它的鏈接地址。
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調試就是基於軟件斷點的調試,我們可以用gdb對程序代碼的某一行進行斷點設置,那么它是如何定位到某個指令的地址的?
這就需要有調試信息,也就是在編譯的時候加上 -g 給程序添加調試信息。
eclipse對gdb進行了進一步的封裝(GUI),我們可以通過對eclipse進行某些設置達到調試arm程序的目的。
1.首先把文件加入工程
2.設置調試配置:
點工具欄上的小蟲子
Debug Configurations...
新建一個調試配置
選擇選項卡Main,在C/C++ Application: 選項上選擇要調試的elf文件
選擇選項卡Debugger,GDB debugger: 選擇為arm-elf-gdb
選擇選項卡Commands, 'Initialize'conmmands 下輸入命令:
target remote 127.0.0.1:3333 //連接openocd
load //加載程序到內存
break _start //設置斷點到_start
c //continue繼續執行
然后Apply ,最后Debug開始調試
3.當然,上述程序是在內存執行的,但是開發板一開始的時候內存還沒初始化,是不可用的,因此我們需要先設置內存
在openocd的命令控制台上(telnet 127.0.0.1 4444進入openocd控制台)
halt //暫停cpu
load_image init.bin 0 //加載內存初始化程序 init.bin 到 0 地址
resume 0 //在0地址開始運行
halt //暫停cpu
然后就可以Debug了
Debug時,當運行到斷點處的時候,我們可以看到某些寄存器或者變量的值,這些值在eclipse上顯示: