CISC處理器調試系統的設計實現,詳細軟硬件架構、流程、代碼
- 前言
隨著嵌入式的不斷發展,在各個領域的應用越來越廣泛,由于嵌入式系統的專用性很強,所以針對不同的應用的嵌入式軟件的開發在嵌入式系統開發中所占的比重越來越大。嵌入式系統的開發主要包括兩個部分硬件設計和軟件設計。軟件設計的步驟主要有源碼編輯、源碼編譯、嵌入式操作系統的配置、程序下載和調試。由于嵌入式系統的資源有限不可能在嵌入式系統的硬件平臺上集成自身的軟件開發環境,所以嵌入式的軟件開發的通常采用交叉編譯和調試的方式。調試是保證程序質量的重要手段之一,可以驗證程序是否滿足預期的要求和檢查程序存在的bug。交叉的開發方式采用宿主機和目標機的結構。宿主機一般采用PC機,將嵌入式系統的軟件開發環境配置在PC機上。宿主機和目標機之間通過串口、并口和網線等建立連接,不僅僅是物理連接還有邏輯連接。在交叉開發過程中宿主機和目標機通過這種連接進行交互,完成目標程序的編譯下載和調試。
嵌入式系統的開發主要針對硬件系統中的微處理器的嵌入式軟件的開發,嵌入式系統的軟件調試也是針對微處理器的調試?,F在微電子技術飛速發展,處理器生產工藝也不斷提高,微處理器芯片的集成度更高、運行頻率更高,所以對調試的要求更高。單單采用PC機上的軟件調試器和軟件調試代理已經很難適應這些新的變化,將調試功能轉移到硬件部分為嵌入式軟件的開發提供更好的保障和支持,實現成本也比較低。微處理器芯片中集成支持調試的硬件邏輯已經逐漸成為趨勢。
在板級的測試和調試領域,為了更好的支持對電路物理節點的訪問,JTAG標準已經被很多芯片生產廠商所采用。JTAG標準最早的提出是為了檢測印刷電路板的元件焊接問題,通過在電路中引入邊界掃描單元所組成的邊界掃描鏈來完成對電路節點的訪問?,F在JTAG標準也被應用于嵌入式軟件的調試過程中,用于與硬件調試邏輯交互提供通用的調試接口。
- 總體方案設計
圖1 系統結構框圖
整個調試系統分為四部分PC機上層控制臺,USB-JTAG協議轉換器,片上調試器OCD(On Chip Debugger)以及調試的目標處理器CPU。
- 系統硬件
- USB傳輸
USB是以串行傳輸的方式傳輸數據,首先使用FTDI公司的USB串并轉換芯片FT245R將USB串行數據轉換為并行數據,然后USB-JTAG協議轉換器根據接收到的數據按照JTAG協議輸出TAP信號。USB-JTAG協議轉換器的結構如圖1所示。
圖 1 協議轉換器的結構
USB-JTAG協議轉換器與FT245R之間除了有8位的數據Data[7:0]的傳輸,還有四個握手信號,分別是nRXF、nTXE、nRD和WR,如圖1所示。nRXF是讀FIFO_TX允許信號,nTXE是寫FIFO_RX允許信號,還有讀FIFO_TX信號nRD和寫FIFO_RX信號WR。當nRXF為低電平時說明FIFO_TX不為空,USB-JTAG協議轉換器可以從中讀出數據,此時USB-JTAG協議轉換器可以通過發送nRD信號從FIFO_TX讀取數據;同樣當nTXE信號有效的時候表明FIFO_RX還有空間,此時USB-JTAG協議轉換器可以使WR信號有效往FIFO_RX中寫入數據。USB-JTAG協議轉換器對FIFO_TX和FIFO_RX的讀寫操作都是以字節為單位。
FT245R內部有兩個FIFO分別為FIFO TX Buffer和FIFO RX Buffer,FIFO TX Buffer負責存放接收從PC機發送來的數據,FIFO RX Buffer負責接收從USB-JTAG協議轉換器發送來的數據,為了區分稱之為FIFO_TX和FIFO_RX。FT245R芯片的內部結構如圖2所示。
圖2 FT245R芯片的內部結構
- SPARTAN-3E開發板
采用xilinx的SPARTAN-3E開發板,將目標處理器與片上調試器的硬件邏輯還有協議轉換器中的JTAG信號的生成功能都集成到該開發板的FPGA上。系統如圖3所示。
圖3
- 片上調試器結構
圖4 片上調試器結構
TAP控制器掌管JTAG協議的狀態機,控制OCD與USB-JTAG協議轉換器之間的數據和指令的移入移出。TAP(Test Access Port)包含四個引腳用來控制指定的操作。這四個引腳分別為TMS,TCK,TDI,TDO。TAP控制器內部采用標準的JTAG協議狀態機來控制TAP的數據通路,包括指令寄存器掃描鏈和數據寄存器掃描鏈的選擇以及掃描鏈數據的傳輸。
寄存器包括邊界掃描寄存器、BYPASS寄存器、斷點寄存器和指令寄存器。邊界掃描寄存器在此處是為讀取處理器輸入輸出引腳預留的擴展寄存器;BYPASS寄存器是位寬為1的寄存器,當在多個器件或模塊串聯的時候用該寄存器來旁路當前器件或模塊;指令寄存器主要用來存放對CPU進行調試的相應調試指令。
掃描鏈包括寫PC掃描鏈和自定義數據掃描鏈。寫PC掃描鏈是為了寫入PC值而設計的掃描鏈,而通過自定義數據掃描鏈可以讀出處理器內部的狀態和數據。
處理器運行控制模塊是片上調試器的核心部件,負責調試指令的譯碼以及讀CPU寄存器、復位、斷點設置檢測和處理器運行控制,還有寫CPU內部程序計數器PC等調試功能的實現。
- 處理器運行控制模塊
處理器運行控制模塊是片上調試器的核心部件,負責指令譯碼和根據當前指令和CPU的運行狀態進行機器指令或者微指令的單步和斷點的判定,并且根據判定結果控制CPU的運行。指令譯碼就是根據PC上層平臺發送到指令寄存器中的指令來產生相應的控制信號,直接通過這些控制信號控制CPU的運行、停止和復位等。設計了9條指令,分別為:
1)SREAD:CPU停止,并且此時選通CPU內部掃描寄存器數據鏈讀出CPU內部主要寄存器的值。
2)STEP:微指令的單步,CPU運行一條微指令然后停下來。
3)MSTP:機器指令的單步,CPU運行一條機器指令然后停下來。
4)BPSET:斷點設置,該指令只負責產生斷點設置所需要的相應控制信號,并不負責斷點數據的寫入。實際的斷點數據是用戶通過PC機的上層工具設置以后,再進行一個BPR的數據寫入來完成的。
5)RUN:CPU運行指令。
6)BRUN:斷點運行,在斷點設置完成以后,發送該指令來使CPU運行。
7)RESET:復位指令,使CPU復位。
8)WPC:寫PC指令,為用戶提供對CPU內部程序計數器PC值進行寫入的功能,以滿足某些用戶的特殊需求。
9)STOP:CPU停止指令。
上面所描述的9條指令, 其中BPSET和BPRUN指令是兩條相互依賴的調試指令,兩條指令聯合完成斷點調試功能。其他的指令都是一條指令完成相應的調試功能。
- 斷點設置和檢測
首先要通過外部來設置斷點值,硬件部分要設計一個斷點寄存器BPR用來存放用戶設置的機器指令斷點或者微指令斷點值,該寄存器位寬為24,其中低18位為有效數據位,高6位作為預留的擴展位。通過邊界掃描的方式將斷點值串行的移入到斷點寄存器BPR中。
BPR[17:16]兩位為標志位用來進行斷點類型的區分,當BPR[17:16]=00時表明要寫入的是微指令斷點,此時BPR[8:0]為要寫入的微指令的斷點值即斷點微地址;當BPR[17:16]=01時表示要寫入的是機器指令斷點,此時BPR[15:0]為要寫入的機器指令的斷點值即內存機器指令的地址。
斷點的檢測首先根據標志位來區分斷點類型,是微指令斷點還是機器指令斷點。當標志位為00時,將斷點值與微指令地址進行比較,其值一致時產生斷點觸發信號;當標志位為01時,將斷點值與PC寄存器中的機器指令地址進行比較,如果一致同樣產生斷點觸發信號。
- PC值的寫入
處理器調試的過程中,為了能夠隨時控制處理器所要執行的指令,需要設置PC(程序計數器)值即所要執行的指令的地址。采用邊界掃描技術來實現該功能,設計一條掃描鏈通過該掃描鏈將要設置的PC值寫入到PC寄存器中,掃描鏈的結構如圖5所示。
圖5 寫PC掃描鏈
由于CISC處理器內部的寄存器在寫入和讀出時都有相應的使能信號,所以在寫入PC值的時候需要使PC的使能信號PCce有效,而這些寄存器的使能信號的產生是由微指令譯碼得來的,如果要修改微指令會影響到其他寄存器的使能控制存在一定的風險。
為了解決這個問題可以有兩種方法可供選擇:
1、將uIR數據讀出,PC寫操作完成以后再寫回
該方法是先將uIR內部的內容讀出保存好,然后寫入帶有PC寄存器使能控制信號微指令,當PC值正確寫入以后再將原來保存的uIR的值還原到uIR寄存器中。
2、引入偽微指令寄存器用來在寫入PC值取代uIR輸出微指令
該方法是在微指令寄存器uIR到微指令譯碼模塊uIR_Decoder之間加入一個掃描寄存器BSC_uIR,稱之為偽微指令寄存器,這個寄存器在保證不影響uIR的前提下產生PCce信號。當寫入PC值時首先選中該掃描鏈,然后將要寫入PC的數據移入BSC_PC_A中,PCce有效則將BSC_PC_A中數據更新到PC中,完成PC的寫操作。
第一種方法操作起來比較繁瑣并且對軟件的設計要求也比較高,在PC機和硬件平臺指令就會存在反復傳送數據的局面增加了數據出錯的幾率。而第二種方法實施起來比較簡單,并且只要將需要的微指令和要寫入的PC值一起進行一次寫操作就可以完成,還保證了uIR寄存器中原有的微指令保持不變。因此本文采用了第二種方法。
- 處理器內部狀態讀出
處理器內部寄存器反映處理器內部運行的狀態和當前一些主要數據,在調試過程中必須能夠將這些數據讀回給用戶。這樣就需要在處理器內部構建一條自定義數據掃描鏈,當執行處理器內部數據讀出調試功能時先選中該掃描鏈,然后將該掃描鏈內部數據讀回到PC機上層控制臺。處理器內部自定義數據掃描鏈的結構如圖6所示。
圖 6 自定義數據掃描鏈
構建數據掃描鏈可以考慮在在寄存器的輸入或者輸出線上加邊界掃描單元的方法來捕獲數據,而不直接對寄存器本身進行操作,這樣就將片上調試器對CPU的侵入性降到最低,保證了CPU內部數據通路的獨立性。
由于在處理器內部寄存器的值的更新都有嚴格的時序控制,所以將掃描寄存器加在寄存器的輸入線和輸出線上是有區別的。這些寄存器輸入線上的數據要存入到寄存器中在下一個時鐘周期輸出才會生效,例如IR中指令輸出到微控制部件去譯碼才會起作用。所以為了要了解當前正在起作用的這些寄存器的值,另外輸入線上的值隨時都可能變化,由于這兩個原因在輸入線上引入邊界掃描寄存器才可以真實的反映處理器當前的狀態和寄存器的值。
- 系統軟件設計
調試系統不僅需要底層硬件的良好支持,還需要有一個便于用戶使用的PC機上層的控制臺。該控制臺主要功能是發送數據到串并轉換芯片FT245R,數據經過FT245R轉換以后變為并行的8bit數據送入到USB-JTAG協議轉換器,協議轉換器將數據進行解析來相應的產生TAP信號。
PC機通過USB電纜與FT245R相連,所以PC機只要將數據發送到FT245R任務就完成了,其他的都由下面的硬件來實現。采用C++builer6.0為PC機控制臺的開發平臺,添加FT245R廠商提供的動態鏈接庫,使用FT245R的廠商提供的API函數進行編程實現。
- 系統調試和測試
- 各調試功能的驗證
- 測試程序
當OCD、USB-JTAG協議轉換器和PC機控制臺這三個片上調試系統的組成部分都設計好以后,下一步的工作就是來編寫一段匯編程序作為目標測試程序,因為目標處理器是一款CSIC處理器,所以還必須設計好一段可用的微程序存放到處理器內部控制存儲器中來完成整個處理器控制信號的產生。
由于處理器內存地址0000~002F作為堆棧使用,所以內存中存放的機器指令必須從地址0030開始存放,本文在xilinx的SPARTAN-3E開發板上實現處理器以及片上調試器,所以同時也將編寫好的測試程序生成存儲器初始化文件,然后采用xilinx的RAM核將編輯好的存儲器文件初始化到該RAM核中。在處理器上電時的程序入口地址設置為測試程序的入口即可。
現在編寫一段測試程序如下:
0030:0761 0100; MOV #100H,R1
0032:043A 0002; MOV R1,0002H
0034:2b68 0001; TEST #0001H, R0
0036:019a 000B; JZ 000BH
左邊是在機器指令以及其在內存中的位置,右邊是其對應的匯編程序。其中共有四條指令,包括對通用寄存器、內存等資源的訪問,跳轉指令是程序的跳躍執行,由于在此處關注的是處理器的內部狀態,所采用的測試程序只要能夠覆蓋整個處理器的數據通路即可。
- 復位功能驗證
復位功能是指當系統出現異?;蛘咛幱诘臓顟B用戶不能確定時,可以使用該功能使處理器回到初始狀態。由于處理器內部與處理器初始運行有關的寄存器初始值都是確定的值,所以要驗證復位調試功能,只需將復位調試指令發送到OCD,然后讀出處理器內部寄存器的值與寄存器的初始值是否相同來確定復位調試功能是否正確執行。
首先來看一下處理器內部一些寄存器的初始值,在處理器內部堆棧指針SP、程序計數器PC和中斷允許寄存器MASK有特別的初始值,其他寄存器都為0值,SP初始值為0030H,PC值也為0030H,因為在處理器運行時SP從0030H往小地址減而PC值則是往大地址執行。而MASK初始值為5AA5,設置這樣的初始值主要是為了容易檢測數據在讀出時是否出現錯位的現象。
執行處理器復位調試功能,然后讀出內部寄存器的值,看是否回到初始狀態,PC機控制臺顯示出讀出的寄存器值如圖1,可以看出所有的寄存器都回到了初始狀態,表示復位調試功能實現正確。
圖 1 復位功能驗證
- 微指令單步
微指令單步主要是在執行一條機器指令過程中,為了能更清楚詳細的處理器內部具體操作涉及到具體的控制信號起作用以及某些寄存器的操作。本文的測試程序的第一條機器指0761 0100(MOV #100H,R1),是將立即數十六進制的100移動到通用寄存器R0中。根據第三章介紹的微程序的設計和微指令的轉移方式,寫出該機器指令所對應的微指令地址和微指令。
000:20080001;
001:00069002;
002:CC000003;
003:00000404;
004:00000A08;
00B:2008000F;
00F:00069C10;
014:C0080015;
015:00061016;
016:D0000006;
在單步調試過程中將數據讀回與以上的分析相比較,將指令0761 0100的單步調試過程每一個單步的數據都讀回,其中將微指令單步中的主要界面截圖如圖2、圖3、圖4和圖5。
圖2第一條微指令
圖3 第二條微指令
圖4 讀數據微指令
圖5 結果寫入R1
通過觀察UAR、DR、IR、R1、PC和AR六個寄存器值的變化,可知系統正常按照預期運行,并且單步調試功能正確實現。
- 微指令斷點
微指令斷點調試時,首先通過斷點設置將微指令斷點值寫入到斷點寄存器。其中斷點寄存器BPR中為顯示正是通過PC機控制臺寫入到BPR寄存器中值,說明斷點值已經正確的寫入。然后運行處理器,由于當處理器運行停止時讀取處理器內部寄存器狀態,結果返回如圖6。其中UAR顯示現在處理器停止的微指令的位置,讀出的其他寄存器值也是運行到當前微指令斷點的值。
圖6 微指令斷點返回結果
- 連續運行和停止
連續運行是處理器運行在正常情況下,此時并不需要片上調試器的干涉,至于停止運行則是讓處理器運行完當前機器指令則停止。由于在內存中存儲的程序很短,而處理器的運行速度很快,所以在發送完連續運行調試指令,可以馬上執行停止運行調試指令內存中的測試指令已執行完成了,所以在停止運行指令之后再通過PC機控制臺來讀取處理器內部寄存器的值就不會改變了。如7、8兩張截圖是停止運行指令之后兩次讀取數據的結果,可以看出結果不再變化,證明停止調試指令正確實現。
圖7 第一次讀結果
圖8 第二次讀結果
- 總結
在嵌入式系統的開發過程中,調試是不可或缺的一環。一個好的調試器可以大大的提高系統開發的效率,縮短推出產品的時間,同時也提高了系統的可靠性。
本文設計了一個基于JTAG協議的片上調試器,該片上調試器實現了微指令和機器指令的單步、斷點以及讀取處理器內部寄存器和寫入PC、處理器復位等常用調試功能。構建掃描鏈時采用獨立的掃描通路不對處理器本身寄存器做任何修改,這樣在保證實現調試功能的同時還最大程度的保護了處理器數據通路的獨立性,將對處理器的侵入性降到一個比較低的水平。
評論