摘要:MAXQ?微控制器提供的JTAG啟動加載程序使外部JTAG主機能夠利用一組標準命令,輕松地識別MAXQ微控制器,并對其進行編程。本應用筆記中的代碼可以用作構建全功能JTAG啟動加載主機應用程序的出發點。主機應用程序能夠識別、初始化、裝載、驗證支持標準啟動加載程序命令集MAXQ微控制器的程序和數據存儲器內容。
本應用筆記涉及到實現MAXQ2000 JTAG啟動加載程序主機的基本步驟。這些步驟包括JTAG端口接口,測試訪問端口(TAP)控制器通信,激活啟動加載程序模式,向基于ROM的啟動加載程序發送命令等。由于所有MAXQ器件的JTAG端口工作情況一般相同,MAXQ啟動加載程序采用共享命令集工作,因此,在實現MAXQ微控制器JTAG啟動加載程序主機時可以參考本應用筆記涉及到的大部分主題(以及大部分實例代碼)。
除了串口,應用筆記并沒有使用MAXQ2000的特殊功能。這表明,這里的實例代碼很容易重新用于程序存儲器空間足夠大的任何MAXQ20器件。代碼以MAXQ匯編語言編寫,采用MAX-IDE開發環境編譯??梢?a href="http://www.nxhydt.com/soft/special/" target="_blank">下載這些代碼。
在原型區安裝一個2 x 5引腳插座對主機MAXQ2000評估板進行改動,原型區提供JTAG電纜主機側連接。插座的引腳符合標準MAXQ JTAG插座布局,按照表1所示進行連接。
表1. MAXQ2000 JTAG連接
不需要對從機MAXQ2000評估板進行改動。按照上面的說明在主機MAXQ2000評估板的原型區安裝2 x 5 JTAG插座。然后,將兩塊評估板連接起來;主機評估板原型區的2 x 5 JTAG插座和從機評估板的標準JTAG插座(J4)之間連接標準2 x 5 JTAG電纜(這種JTAG一般用于連接串口至JTAG板和MAXQ評估板)。JTAG 2 x 5連接器含在MAXQ2000評估套件中。
為簡化起見,沒有對主機評估板和從機評估板的JTAG電纜電源或者參考電壓連接進行試驗。而是設置兩塊評估板采用同一VDDIO電壓(大約3.6V)工作。這種設置保證了主機和從機MAXQ2000采用公共I/O電源電平工作。
從機評估板還在插座J3上安裝了LCD子卡(MAXQ2000-K01)。表2列出了兩塊電路板(以及串口至JTAG電路板)的跳線和DIP開關設置。注意:應斷開未列出的所有跳線。圖1所示為最終設置。
表2. 電路板開關和跳線設置
圖1. JTAG演示板配置
表3. JTAG接口信號
從技術上看,nRESET引腳并不是JTAG接口的組成部分。它含在JTAG電纜中,使JTAG主機能夠復位從機微控制器。重新設置從機微控制器是進入啟動加載程序模式需要的步驟,如果JTAG通信意外中斷,也需要重新設置從機微控制器。
JTAG接口是全雙工的,數據在TDI線上由主機送入從機,同時,數據在TDO線上由從機送入主機。從機在TCK上升沿對到達數據(在TDI和TMS上)進行采樣,在TCK下降沿,數據在TDO上被驅動輸出至主機。對于到達和輸出數據,最先傳送最低有效位。本應用筆記簡要介紹JTAG接口和TAP控制器,以解釋實例代碼的工作。關于這些特性的詳細討論,請參考MAXQ系列用戶指南(English only)的測試訪問端口(TAP)、在線調試模式、在系統編程等章節,公司網站上有該文檔。
圖2. 測試訪問端口(TAP)狀態機
TAP控制器的狀態機提供對兩個控制寄存器的訪問,而寄存器提供啟動加載程序接口、調試接口以及其他功能。
圖3. TAP控制器中的寄存器訪問
如圖3所示,DR根據IR值而指向三個內部寄存器之一。
由于這一例子中的從機MAXQ2000安裝了8MHz時鐘晶振,主機能夠驅動JTAG時鐘達到1MHz,而不會出現問題。對于這個例子,100kHz JTAG時鐘足夠了。
對于所有的JTAG移位寄存器操作,隨著新數值的移入,寄存器的當前內容被移出(由TDO)。但是,移出的數值總是固定的(001b);這是由JTAG標準在測試JTAG接口功能時決定的。
比特移入和移出移位寄存器的過程(IR或者DR)是一樣的;TAP狀態機必須分別處于Shift-IR或者Shift-DR狀態,TAP控制器在每個TCK周期的上升沿對輸入比特(在TDI)進行采樣,而在TCK周期下降沿驅動輸出比特(在TDO)。
作為一個例子,在表4中,JTAG主機將數值100b (系統編程模式)移入到IR寄存器中。IR寄存器開始設置旁路值011b;TAP控制器最初為Run-Test-Idle狀態。如下面的圖4所示,比特以最低有效位在前、最高有效位在后移入(移出)TAP控制器。因此,在第一個移位周期,新數值的第0位被移入,舊數值的第0位被移出。
表4. 指令寄存器移位實例
下面是執行這一操作的例程shiftIR3。
激活系統編程模式后,裝入和卸載DR寄存器的操作如下。
然而,啟動加載程序代碼和JTAG主機并不同步。只要JTAG時鐘保持低于MAXQ系統時鐘1/8的最大值,由于JTAG是同步接口,因此,兩路時鐘的確切值并不影響通信。但是,MAXQ系統時鐘速率以及接收到的啟動加載程序命令特性將決定啟動加載程序接收命令和發送回應之間的延時。例如,1MHz運行的MAXQ2000響應某一啟動加載程序命令的時間要比10MHz的MAXQ2000時間長,即使兩個微控制器都可以采用100kHz的JTAG時鐘進行通信。只是讀并返回信息的命令,例如返回ROM標志ID的命令以及從程序存儲器讀取的命令,花費的時間也要少于編程閃存操作等命令。
通過JTAG接口傳送的數據沒有被緩沖。如果在前一命令被讀取之前,發送了另一10位命令,前一命令的結果丟失。ROM代碼和TAP控制器保證前一數據被JTAG主機卸載前,啟動加載程序不會發送其他數據,但反方向還是需要同步。JTAG主機需要通過某種方式知道移入DR的前一字節是否已經被啟動加載程序讀取了。這樣,JTAG主機能夠知道什么時候發送下一字節。采用的方法是利用TAP控制器發送的其他兩個狀態位,以及啟動加載程序輸出的每個8位字節。
圖4. 通過DR的移位數據和狀態位
2x5 如上面的圖4所示,在TAP調試模式下,移入和移出DR的數據包括8個數據位(第2位到第9位)和兩個狀態位(第0位和第1位)。當JTAG主機移入數據時,只使用8個數據位。TAP控制器沒有使用的兩個狀態位(也必須被移入),可以被設置為零,或者任何其他值。
在TAP控制器移出的10位數值中,兩個狀態位提供啟動加載程序或者調試引擎的狀態信息。當啟動加載程序運行時,一般只能達到最后兩個狀態(調試忙或者調試有效),這是因為其他兩個狀態值不會出現在啟動加載程序模式中。(參見圖4中的狀態/條件)
對于其他的MAXQ啟動加載程序,MAXQ2000啟動加載程序提供的命令被劃分成從0到15的命令集。每一命令以命令字節開始,它包括命令集(前四個比特)以及命令專用數(后四個比特),如表5所示。作為一般規則,命令集0的命令本質上用于提供信息,所有器件均采用它;其他命令集可選。為確定某一MAXQ器件支持的命令集,請參考器件文檔。命令集0的命令05h (獲得支持的命令)返回一個位掩碼,說明啟動加載程序支持的其他命令集。
MAXQ2000支持以下的啟動加載程序命令集。
表5. MAXQ加載程序命令集
作為演示的一部分,我們的實例程序獲得該信息,然后打印輸出至串口。用于實現該功能的例程是getBanner。
取決于MAXQ器件,這一02h (主機擦除)命令可能需要幾秒鐘的時間來完成。由于這是一個單字節命令,確定該命令什么時候完成的最簡單方法是不斷發送無操作(00h)命令,其后是1毫秒的延遲,直到啟動加載程序返回3Eh,表明命令已經完成。下面的 masterErase例程說明了這一方法。
如果最后一條命令成功完成,狀態碼總是00h (無錯誤)。非零狀態碼指示有錯誤。MAXQ2000用戶指南附錄(English only)列出了所有的狀態碼;這里列出了幾個常見錯誤碼。
裝入MAXQ2000的代碼基于下面的簡單演示工程。
在裝入代碼前,JTAG通信演示應用程序首先告訴用戶輸入一個4位十進制數,然后修改要裝入的應用程序,如下所示。
硬件
圖5. 演示應用程序,串口提示符
現在輸入一個4位十進制數;不需要隨后按下回車鍵。演示應用程序會完成剩下的操作(主機擦除、裝入代碼和卸載代碼),并輸出結果,以及從程序存儲器中卸載的十六進制字節值,如圖6所示。
圖6. 演示應用程序,串口輸出
簡介
具有可在線編程的程序存儲器(例如MAXQ2000和MAXQ3210)的MAXQ微控制器一般還提供基于ROM的啟動加載程序,利用微控制器的JTAG兼容調試端口,實現程序存儲器的加載。盡管不同的器件有不同的JTAG啟動加載程序功能,但是通常都包括程序和數據存儲器寫、讀、驗證和擦除等命令。有的器件為啟動加載程序提供其他接口(例如,串口或者SPI?接口),而JTAG接口是最常用的,原因有兩個。第一,JTAG接口支持在線調試功能,第二,最終用戶應用程序并沒有充分發揮JTAG接口的功能(與串口不同)。一旦加載程序代碼后,可選擇的加密機制限制了對啟動加載程序的訪問,或在線調試。關于每個MAXQ器件功能的詳細信息,請參考產品說明,包括數據資料和用戶指南等。本應用筆記涉及到實現MAXQ2000 JTAG啟動加載程序主機的基本步驟。這些步驟包括JTAG端口接口,測試訪問端口(TAP)控制器通信,激活啟動加載程序模式,向基于ROM的啟動加載程序發送命令等。由于所有MAXQ器件的JTAG端口工作情況一般相同,MAXQ啟動加載程序采用共享命令集工作,因此,在實現MAXQ微控制器JTAG啟動加載程序主機時可以參考本應用筆記涉及到的大部分主題(以及大部分實例代碼)。
除了串口,應用筆記并沒有使用MAXQ2000的特殊功能。這表明,這里的實例代碼很容易重新用于程序存儲器空間足夠大的任何MAXQ20器件。代碼以MAXQ匯編語言編寫,采用MAX-IDE開發環境編譯??梢?a href="http://www.nxhydt.com/soft/special/" target="_blank">下載這些代碼。
硬件設置
采用一對MAXQ2000評估(EV)板來開發本應用筆記的實例代碼。需要兩塊MAXQ2000評估板執行這里的軟件。一個MAXQ2000 (JTAG主機)運行實例代碼;第二個MAXQ2000用作JTAG從機,由主機對它重新編程。兩個MAXQ2000微控制器都采用了標準8.00MHz晶振。在原型區安裝一個2 x 5引腳插座對主機MAXQ2000評估板進行改動,原型區提供JTAG電纜主機側連接。插座的引腳符合標準MAXQ JTAG插座布局,按照表1所示進行連接。
表1. MAXQ2000 JTAG連接
JTAG Header Pin | JTAG Cable Function | MAXQ2000 JTAG Master Connection |
MAXQ2000 JTAG Slave Connection |
1 | TCK (Test Clock) | P0.0 (Output) | P4.0 (Input) |
2 | GND | GND | GND |
3 | TDO (Test Data Out) | P0.1 (Input) | P4.3 (Output) |
4 | VREF | – | – |
5 | TMS (Test Mode Select) | P0.2 (Output) | P4.2 (Input) |
6 | nRESET | P0.4 (Open Drain) | nRESET (Input) |
7 | Keyed pin | – | – |
8 | +5V | – | – |
9 | TDI (Test Data In) | P0.3 (Output) | P4.1 (Input) |
10 | GND | GND | GND |
不需要對從機MAXQ2000評估板進行改動。按照上面的說明在主機MAXQ2000評估板的原型區安裝2 x 5 JTAG插座。然后,將兩塊評估板連接起來;主機評估板原型區的2 x 5 JTAG插座和從機評估板的標準JTAG插座(J4)之間連接標準2 x 5 JTAG電纜(這種JTAG一般用于連接串口至JTAG板和MAXQ評估板)。JTAG 2 x 5連接器含在MAXQ2000評估套件中。
為簡化起見,沒有對主機評估板和從機評估板的JTAG電纜電源或者參考電壓連接進行試驗。而是設置兩塊評估板采用同一VDDIO電壓(大約3.6V)工作。這種設置保證了主機和從機MAXQ2000采用公共I/O電源電平工作。
從機評估板還在插座J3上安裝了LCD子卡(MAXQ2000-K01)。表2列出了兩塊電路板(以及串口至JTAG電路板)的跳線和DIP開關設置。注意:應斷開未列出的所有跳線。圖1所示為最終設置。
表2. 電路板開關和跳線設置
Board | Switch or Jumper | Setting | Notes |
Serial-to-JTAG Board | JH1 | Connected | ? |
JH2 | Connected | ||
JH3 | Connected | Supplies 5V power over JTAG cable | |
Master MAXQ2000 EV Kit | JU1 | Pins 1 and 2 connected | Powers VDD from 2.5V supply |
JU2 | Pins 1 and 2 connected | Powers VDDIO from 3.6V supply | |
JU3 | Pins 1 and 2 connected | Powers VLCD from 3.6V supply | |
JU11 | Connected | Powers kit board from JTAG 5V supply | |
DIP SW1 | Switches #4 and #8 ON; all other switches OFF | Enables serial port 0 output to J5 | |
DIP SW3 | All switches OFF | ||
DIP SW6 | All switches OFF | ||
Slave MAXQ2000 EV Kit | JU1 | Pins 1 and 2 connected | Powers VDD from 2.5V supply |
JU2 | Pins 1 and 2 connected | Powers VDDIO from 3.6V supply | |
JU3 | Pins 1 and 2 connected | Powers VLCD from 3.6V supply | |
DIP SW1 | All switches OFF | ||
DIP SW3 | All switches OFF | ||
DIP SW6 | All switches OFF |
圖1. JTAG演示板配置
MAXQ JTAG接口
MAXQ微控制器的JTAG接口由四條信號線組成,用于測試訪問端口(TAP)控制器的信息輸入和輸出。TAP控制器支持對MAXQ啟動加載程序的訪問,提供在線調試功能(注意,調試主機的實現和啟動加載程序主機的實現類似,但是已經超出了本應用筆記的范圍)。表3對四條JTAG信號線進行了說明。表3. JTAG接口信號
JTAG Signal | Signal Name | Direction (Master) | Direction (Slave) | Signal Description |
TMS | Test Mode Select | Output | Input | This signal line, along with the TCK line, is used to shift the TAP controller from one operational state to the next. |
TCK | Test Clock | Output | Input | This signal provides the clock for the JTAG interface. The JTAG clock is limited to a maximum of the slave's clock frequency divided by 8. For example, if the slave is running at a clock frequency of 8MHz, the JTAG clock at TCK cannot run any faster than 1MHz. |
TDI | Test Data In | Output | Input | This signal carries data that is sent from the master to the slave. |
TDO | Test Data Out | Input | Output | This signal carries data that is sent from the slave back to the master. |
從技術上看,nRESET引腳并不是JTAG接口的組成部分。它含在JTAG電纜中,使JTAG主機能夠復位從機微控制器。重新設置從機微控制器是進入啟動加載程序模式需要的步驟,如果JTAG通信意外中斷,也需要重新設置從機微控制器。
JTAG接口是全雙工的,數據在TDI線上由主機送入從機,同時,數據在TDO線上由從機送入主機。從機在TCK上升沿對到達數據(在TDI和TMS上)進行采樣,在TCK下降沿,數據在TDO上被驅動輸出至主機。對于到達和輸出數據,最先傳送最低有效位。本應用筆記簡要介紹JTAG接口和TAP控制器,以解釋實例代碼的工作。關于這些特性的詳細討論,請參考MAXQ系列用戶指南(English only)的測試訪問端口(TAP)、在線調試模式、在系統編程等章節,公司網站上有該文檔。
TAP控制器通信
TAP控制器圍繞狀態機進行構建,如下面的圖2所示。TAP狀態機中有16個分立狀態。根據TMS信號值,在TCK的上升沿從一個狀態向下一個狀態轉變。例如,如果TAP控制器處于Select-DR-Scan狀態,TCK出現了上升沿:- 如果TMS = 1,TAP控制器將轉換到Select-IR-Scan狀態。
- 如果TMS = 0,TAP控制器將轉換到Capture-DR狀態。
- 5個'1'轉換(保持TMS高電平,同步TCK 5個周期)總是使狀態機回到Test-Logic-Reset,而不論起始狀態如何。這表明,如果不確定TAP控制器當前的狀態,或者在某些情況下JTAG主機和從機間的通信中斷,總是可以通過同步5個'1'轉換,使TAP控制器回到已知狀態。
- 即使TCK時鐘繼續運行,也可以暫停JTAG通信,不確定地保持在Run-Test-Idle、Pause-DR或者Pause-IR狀態,而不影響TAP控制器的狀態。
圖2. 測試訪問端口(TAP)狀態機
TAP控制器的狀態機提供對兩個控制寄存器的訪問,而寄存器提供啟動加載程序接口、調試接口以及其他功能。
- IR (指令寄存器)寬度總是3位。該寄存器可以用作指數寄存器,控制DR的功能(參見下面)。
- DR (數據寄存器)是TAP控制器中幾個寄存器的訪問點。當比特移入或者移出DR時實際訪問的寄存器取決于IR當前值。
圖3. TAP控制器中的寄存器訪問
如圖3所示,DR根據IR值而指向三個內部寄存器之一。
- 如果IR = 011b,TAP控制器處于Bypass模式。在這一模式下(這是TAP控制器的默認模式),通過TDO,移入到DR (通過TDI)的數據被直接移回送出。通過TAP控制器移動數據并沒有改變內部寄存器。
- 設置IR = 100b,使TAP控制器處于System Programming模式。在這種模式下,移入DR中的數據被移入到3位系統編程寄存器中。該寄存器(也可以通過MAXQ微控制器ICDF寄存器的[3:1]位進行訪問)控制MAXQ復位后進入正常程序執行模式還是啟動加載程序模式。如果使能啟動加載程序模式,它還控制啟動加載程序使用哪一接口(JTAG、串口或者SPI)。
- 設置IR = 010b,使TAP控制器進入Debug模式。在這一模式下,移入DR的數據被移入到內部10位調試寄存器中,可以被啟動加載程序讀取。啟動加載程序輸出的數據也通過該寄存器,在TDO上被移回送出(以及兩個狀態位)。該寄存器被用于啟動加載程序模式和在線調試模式時的數據傳送。
控制JTAG端口和復位線
從機MAXQ2000 (TMS, TCK, TDO和TDI) JTAG/TAP端口的四條線以及nRESET線分別連接至主機MAXQ2000的一個端口引腳??刂艼TAG接口的第一步是正確配置這些線。#define TCK PO0.0 ; Test Clock - Master output #define TDO PI0.1 ; Test Data Out - Slave output, master input #define TMS PO0.2 ; Test Mode Sel - Master output #define TDI PO0.3 ; Test Data In - Master output #define RST PD0.4 ; Reset - Master open-drain output (on 1)四條JTAG線工作在標準驅動模式下。從主機角度看,TMS、TCK和TDI總是被驅動為輸出,而TDO (由從機驅動)總是為輸入。JTAG線的方向固定,不是雙向的。nRESET線是特殊情況,被配置為主機側開漏輸出。通常,從機將自己的nRESET線拉至高電平,因此,主機只能將該線拉低(復位從機時),或者完全釋放它(在其他所有時間)。主機不應將從機的nRESET線驅動為高電平。
;============================================================================== ;= ;= initializeJTAG ;= ;= Sets up the port pins for the JTAG interface. ;= ;= Inputs : None ;= Outputs : None ;= Destroys : None ;= initializeJTAG: move PD0.0, #1 ; TCK - master output move PO0.0, #1 ; Drive high move PD0.1, #0 ; TDO - master input move PO0.1, #1 ; Weak pullup on move PD0.2, #1 ; TMS - master output move PO0.2, #1 ; Drive low move PD0.3, #1 ; TDI - master output move PO0.3, #1 ; Drive high move PD0.4, #0 ; RST - open drain when 1, tristate when 0 move PO0.4, #0 ; Weak pullup off ret端口引腳初始化之后,采用例程clock0和clock1來同步TMS線上的靜態0和1,使TAP控制器從一個狀態轉換到另一狀態。只要JTAG時鐘速率保持低于從機微控制器系統時鐘速率1/8的最大值,JTAG時鐘可以采用任何頻率。這里不需要考慮主機的系統時鐘速率;它不需要和從機系統時鐘速率相匹配。主機可以比從機運行的快或者慢,而不會導致出現JTAG通信問題。
由于這一例子中的從機MAXQ2000安裝了8MHz時鐘晶振,主機能夠驅動JTAG時鐘達到1MHz,而不會出現問題。對于這個例子,100kHz JTAG時鐘足夠了。
#define JCLOCK 40 ; 100kHz : (((10us / (1/8MHz)) / 2) ;============================================================================== ;= ;= clock0 ;= ;= Clocks a zero TMS bit into the JTAG interface. ;= ;= Inputs : None ;= Outputs : None ;= Destroys : LC[0] clock0: move TMS, #0 ; Drive TMS low move LC[0], #JCLOCK djnz LC[0], $ move TCK, #1 ; Clock rising edge move LC[0], #JCLOCK djnz LC[0], $ move TCK, #0 ; Clock falling edge move LC[0], #JCLOCK djnz LC[0], $ ret ;============================================================================== ;= ;= clock1 ;= ;= Clocks a one TMS bit into the JTAG interface. ;= ;= Inputs : None ;= Outputs : None ;= Destroys : LC[0] clock1: move TMS, #1 ; Drive TMS high move LC[0], #JCLOCK djnz LC[0], $ move TCK, #1 ; Clock rising edge move LC[0], #JCLOCK djnz LC[0], $ move TCK, #0 ; Clock falling edge move LC[0], #JCLOCK djnz LC[0], $ ret利用這兩個例程,我們可以增加另一個例程來初始化TAP控制器,迫使它回到Test-Logic-Reset狀態。注意Test-Logic-Reset狀態,正如其名稱的含義,它對TAP邏輯進行徹底復位,包括確定啟動加載程序是否使能以及啟動加載程序使用哪一接口位(SPE和PSS[1:0])。因此,一旦進入啟動加載程序模式,設置TAP控制器為Test-Logic-Reset,對器件進行復位,退出啟動加載程序模式。演示應用程序中使用的JTAG例程(除了testLogicReset本身之外)都假定TAP控制器在例程啟動時處于Run-Test-Idle狀態。在JTAG通信期間,TAP控制器在不同狀態間轉換;例程最后,TAP控制器總是返回到Run-Test-Idle。
;============================================================================== ;= ;= testLogicReset ;= clock0, clock1 ;= ;= Resets the JTAG/TAP controller to its starting state. ;= ;= Inputs : None ;= Outputs : None ;= Destroys : LC[0] ;= testLogicReset: call clock1 call clock1 call clock1 call clock1 call clock1 call clock1 call clock1 call clock0 ; Brings us to Run-Test-Idle ret
寫入TAP指令寄存器
TAP狀態機向下轉換到Shift-IR狀態,同步輸入一個新的3位數值,將數值裝入TAP控制器的IR。在進入Update-IR狀態之前,該數值并沒有實際從移位寄存器復制到指令寄存器中。對于所有的JTAG移位寄存器操作,隨著新數值的移入,寄存器的當前內容被移出(由TDO)。但是,移出的數值總是固定的(001b);這是由JTAG標準在測試JTAG接口功能時決定的。
比特移入和移出移位寄存器的過程(IR或者DR)是一樣的;TAP狀態機必須分別處于Shift-IR或者Shift-DR狀態,TAP控制器在每個TCK周期的上升沿對輸入比特(在TDI)進行采樣,而在TCK周期下降沿驅動輸出比特(在TDO)。
;============================================================================== ;= ;= shift ;= ;= In a shift register state, clocks in a TDI bit and clocks out a TDO bit. ;= ;= Inputs : C - Bit to shift in to TDI. ;= Outputs : C - Bit shifted out from TDO. ;= Destroys : PSW, LC[0] ;= shift: jump C, shift_bit1 shift_bit0: move TDI, #0 ; Shift in zero bit jump shift_bitEnd shift_bit1: move TDI, #1 ; Shift in one bit jump shift_bitEnd shift_bitEnd: move LC[0], #JCLOCK djnz LC[0], $ move TCK, #1 ; Rising edge, TDI is sampled move LC[0], #JCLOCK djnz LC[0], $ move TCK, #0 ; Falling edge, TDO is driven out move LC[0], #JCLOCK djnz LC[0], $ move C, TDO ; Latch TDO value ret對于傳送的每一位,除了最后一位之外,TMS必須保持低電平。這非常重要,因為當每一位移入和移出時,狀態機保持在Shift-IR或者Shift-DR狀態。在最后一個比特周期,TMS必須被驅動為高電平,這樣,隨著最后一位的輸入和輸出,TAP控制器將進入Exit1-DR或者Exit1-IR狀態。
作為一個例子,在表4中,JTAG主機將數值100b (系統編程模式)移入到IR寄存器中。IR寄存器開始設置旁路值011b;TAP控制器最初為Run-Test-Idle狀態。如下面的圖4所示,比特以最低有效位在前、最高有效位在后移入(移出)TAP控制器。因此,在第一個移位周期,新數值的第0位被移入,舊數值的第0位被移出。
表4. 指令寄存器移位實例
TCK | TMS | TDI | TDO | TAP State | Shift Register | Instruction Register | ||||
bit 2 | bit 1 | bit 0 | bit 2 | bit 1 | bit 0 | |||||
0 | 1 | x | x | Run-Test-Idle | x | x | x | 0 | 1 | 1 |
1 | 1 | x | x | Select-DR-Scan | x | x | x | 0 | 1 | 1 |
0 | 1 | x | x | Select-DR-Scan | x | x | x | 0 | 1 | 1 |
1 | 1 | x | x | Select-IR-Scan | x | x | x | 0 | 1 | 1 |
0 | 0 | x | x | Select-IR-Scan | x | x | x | 0 | 1 | 1 |
1 | 0 | x | x | Capture-IR | 0 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | x | x | Capture-IR | 0 | 0 | 1 | 0 | 1 | 1 |
1 | 0 | x | x | Shift-IR | 0 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | 0 | x | Shift-IR | 0 | 0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | x | Shift-IR | 0 | 0 | 1 | 0 | 1 | 1 |
0 | 0 | 0 | 1 | Shift-IR | 0 | 0 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | Shift-IR | 0 | 0 | 0 | 0 | 1 | 1 |
0 | 1 | 1 | 0 | Shift-IR | 0 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | Exit1-IR | 0 | 0 | 0 | 0 | 1 | 1 |
0 | 1 | x | 0 | Exit1-IR | 1 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | x | 0 | Update-IR | 1 | 0 | 0 | 1 | 0 | 0 |
0 | 0 | x | x | Update-IR | 1 | 0 | 0 | 1 | 0 | 0 |
1 | 0 | x | x | Run-Test-Idle | x | x | x | 1 | 0 | 0 |
下面是執行這一操作的例程shiftIR3。
;============================================================================== ;= ;= shiftIR3 ;= clock0, clock1, shift ;= ;= Shifts a 3-bit value into the IR register. ;= ;= Inputs : A[0] - Low three bits contain value to shift into IR ;= Outputs : None ;= Destroys : AP, APC, A[0], PSW, LC[0] ;= shiftIR3: move APC, #80h ; Acc => A[0], turn off auto inc/dec call clock1 ; (Select DR Scan) call clock1 ; (Select IR Scan) call clock0 ; (Capture IR - loads 001b to shift register) call clock0 ; (Shift IR) move TMS, #0 ; Drive TMS low move C, TDO ; xxxxx210 c = s rrc ; sxxxxx21 c = 0 call shift ; Shift in IR bit 0 rrc ; ssxxxxx2 c = 1 call shift ; Shift in IR bit 1 rrc ; sssxxxxx c = 2 move TMS, #1 ; Drive TMS high for last bit call shift ; Shift in IR bit 2 (Exit1 IR) call clock1 ; (Update IR) call clock0 ; (Run Test Idle) ret
寫入TAP數據寄存器
數值移入或者移出TAP控制器DR的操作與裝入/卸載IR的方式相似。通常,只有當IR被設置為兩個數值之一時才能進行這一操作:100b (使TAP控制器進入系統編程模式)或者010b (使TAP控制器進入調試模式)。激活系統編程模式后,裝入和卸載DR寄存器的操作如下。
- DR寄存器移入和移出寬度為3比特。所有三個比特都代表有效數據。
- 當到達Update-DR狀態時,送入DR寄存器的數值被復制到從機微控制器的內部系統編程寄存器中。這三個比特的用法如下。
- 從機微控制器可訪問第0位(讀/寫),它作為寄存器位ICDF.1 (SPE),也被稱為系統編程使能位。復位后,程序ROM檢查該位,確定應進入啟動加載程序模式(SPE = 1)還是正常程序執行模式(SPE = 0)。
- 從機微控制器可訪問第1位和第2位(讀/寫),它作為寄存器位ICDF.2-3 (PSS0-PSS1),也被稱為編程源選擇位。對于能夠為啟動加載程序提供多個接口的微控制器,例如MAXQ2000,這些位用于當SPE = 1時應選擇哪一啟動加載程序接口。當SPE = 0 (正常程序執行模式)時,這些位的設置不起作用。
- DR寄存器傳送出去的數值是系統編程寄存器以前的數值(當進入Capture-DR狀態后,鎖存到移位寄存器中)。
- DR寄存器移入和移出寬度為10比特。對于移出數據,所有10個比特都代表有效數據(8個數據位和2個狀態位)。對于移入數據,只使用了8個數據位;沒有使用兩個狀態位。
- 然后,將移入DR寄存器的高8位卸載,作為啟動加載程序命令的一部分,被啟動加載程序(從程序ROM中運行)讀取。
- 移出DR寄存器的10個比特含有8位由啟動加載程序裝入的數值(作為命令輸出的一部分),以及由TAP控制器設置的兩個狀態信息位。
;============================================================================== ;= ;= shiftDR3 ;= ;= Shifts a 3-bit value into the DR register. This operation should only be ;= performed when IR =100b (System Programming Mode). ;= ;= Inputs : A[0] - Low 3 bits contain value to shift into SPB (PSS1:PSS0:SPE) ;= Outputs : None ;= Destroys : AP, APC, A[0], PSW, LC[0] shiftDR3: move APC, #80h ; Acc => A[0], turn off auto inc/dec call clock1 ; (Select DR Scan) call clock0 ; (Capture DR) call clock0 ; (Shift DR) move TMS, #0 ; Drive TMS low move C, TDO ; xxxxx210 c = s rrc ; sxxxxx21 c = 0 call shift ; Shift in DR bit 0 rrc ; ssxxxxx2 c = 1 call shift ; Shift in DR bit 1 rrc ; sssxxxxx c = 2 move TMS, #1 ; Drive TMS high for last bit call shift ; Shift in DR bit 2 (Exit1 DR) call clock1 ; (Update DR) call clock0 ; (Run Test Idle) ret ;============================================================================== ;= ;= shiftDR ;= clock0, clock1, shift ;= ;= Shifts a 10-bit value into and out of the DR register. This operation ;= should only be performed when IR = 010b (Debug/Loader Mode). ;= ;= Inputs : A[0] - Byte value (input) to shift into DR ;= Outputs : A[0] - Byte value (output) shifted out of DR ;= A[1] - Low two bits are status bits 1:0 shifted out of DR ;= A[15] - Byte value shifted in, cached for use by shiftDR_next ;= Destroys : AP, APC, PSW, LC[0] shiftDR: move APC, #80h ; Acc => A[0], turn off auto inc/dec move A[15], A[0] ; Cache input byte value for use by shiftDR_next sla2 ; Add two empty bits (for status) call clock1 ; (Select DR Scan) call clock0 ; (Capture DR) call clock0 ; (Shift DR) move TMS, #0 ; Drive TMS low move C, TDO ; xxxxxxxx76543210 c = s rrc call shift ; Shift in DR bit 0 rrc call shift ; Shift in DR bit 1 rrc call shift ; Shift in DR bit 2 rrc call shift ; Shift in DR bit 3 rrc call shift ; Shift in DR bit 4 rrc call shift ; Shift in DR bit 5 rrc call shift ; Shift in DR bit 6 rrc call shift ; Shift in DR bit 7 rrc call shift ; Shift in DR bit 8 rrc move TMS, #1 ; Drive TMS high for last bit call shift ; Shift in DR bit 9 (Exit1 DR) call clock1 ; (Update DR) call clock0 ; (Run Test Idle) push Acc ; sddd dddd 10xx xxxx sra4 ; ssss sddd dddd 10xx sra2 ; ssss sssd dddd dd10 and #0003h ; ---- ---- ---- --10 move A[1], Acc ; Return status bits only in A[1] pop Acc and #0FF00h xch ; Return data bits only in A[0] ret
進入JTAG程序加載模式
需要按照以下步驟使MAXQ2000進入JTAG啟動加載程序模式。- 初始化TAP控制器,重新設置它,進入Test-Logic-Reset狀態。
- 設置指令寄存器(IR)為100b,使能系統編程模式。
- 設置數據寄存器(DR)為001b。這使得SPE(系統編程使能)位為1,使能啟動加載程序,設置PSS[1:0] (編程源選擇)位為00b,選擇JTAG接口。
- 保持nRESET低電平,復位MAXQ2000。
- 釋放nRESET。這導致MAXQ2000指向程序ROM (8000h)中的標準復位點。程序ROM代碼將檢查SPE和PSS位值,相應地激活JTAG啟動加載程序。在這一點,啟動加載程序運行,準備接收JTAG命令。
- 設置指令寄存器(IR)為010b,使能調試模式。該模式用于和JTAG啟動加載程序或者調試引擎進行通信;在這一例子中,我們將使用該模式和啟動加載程序進行通信。
- 10位數據移位通過DR,開始向JTAG啟動加載程序發送命令。
#define IR_DEBUG 010b ; Debug Mode #define IR_BYPASS 011b ; Bypass Mode (default) #define IR_SYSTEM_PROG 100b ; System Programming Mode (activate loader) ; System Programming Register settings #define SP_EXECUTE 000b ; Bootloader disabled #define SP_LOAD_JTAG 001b ; Activate JTAG bootloader #define SP_LOAD_UART 011b ; Activate UART bootloader #define SP_LOAD_SPI 101b ; Activate SPI bootloader (invalid on 2000) #define SP_RESERVED 111b ; Reserved value ... call initializeJTAG ; Set up port pins for JTAG call testLogicReset ; Reset JTAG port (ending state: Run-Test-Idle) move Acc, #IR_SYSTEM_PROG call shiftIR3 ; Load the System Programming instruction into IR move Acc, #SP_LOAD_JTAG call shiftDR3 ; Enable the bootloader in JTAG interface mode move RST, #1 ; Drive nRESET low move Acc, #100 ; Delay for 100ms call delayMS call clock0 ; Remain in Run-Test-Idle move RST, #0 ; Release nRESET move Acc, #100 ; Delay for 100ms call delayMS move Acc, #IR_DEBUG call shiftIR3 ; Enable access to the 10-bit debug shift register ;;;; Bootloader commands may now be shifted through the DR register call waitForPrompt ; Verify that the bootloader is responding ...
與加載程序通信
一旦啟動加載程序運行,程序ROM中的啟動加載程序代碼讀取內部寄存器的命令代碼,命令代碼由DR移位寄存器裝入。程序ROM還把結果數據寫入另一內部寄存器,由JTAG主機通過DR寄存器移出。通過這種方式,啟動加載程序代碼和JTAG主機交換信息。然而,啟動加載程序代碼和JTAG主機并不同步。只要JTAG時鐘保持低于MAXQ系統時鐘1/8的最大值,由于JTAG是同步接口,因此,兩路時鐘的確切值并不影響通信。但是,MAXQ系統時鐘速率以及接收到的啟動加載程序命令特性將決定啟動加載程序接收命令和發送回應之間的延時。例如,1MHz運行的MAXQ2000響應某一啟動加載程序命令的時間要比10MHz的MAXQ2000時間長,即使兩個微控制器都可以采用100kHz的JTAG時鐘進行通信。只是讀并返回信息的命令,例如返回ROM標志ID的命令以及從程序存儲器讀取的命令,花費的時間也要少于編程閃存操作等命令。
通過JTAG接口傳送的數據沒有被緩沖。如果在前一命令被讀取之前,發送了另一10位命令,前一命令的結果丟失。ROM代碼和TAP控制器保證前一數據被JTAG主機卸載前,啟動加載程序不會發送其他數據,但反方向還是需要同步。JTAG主機需要通過某種方式知道移入DR的前一字節是否已經被啟動加載程序讀取了。這樣,JTAG主機能夠知道什么時候發送下一字節。采用的方法是利用TAP控制器發送的其他兩個狀態位,以及啟動加載程序輸出的每個8位字節。
圖4. 通過DR的移位數據和狀態位
2x5 如上面的圖4所示,在TAP調試模式下,移入和移出DR的數據包括8個數據位(第2位到第9位)和兩個狀態位(第0位和第1位)。當JTAG主機移入數據時,只使用8個數據位。TAP控制器沒有使用的兩個狀態位(也必須被移入),可以被設置為零,或者任何其他值。
在TAP控制器移出的10位數值中,兩個狀態位提供啟動加載程序或者調試引擎的狀態信息。當啟動加載程序運行時,一般只能達到最后兩個狀態(調試忙或者調試有效),這是因為其他兩個狀態值不會出現在啟動加載程序模式中。(參見圖4中的狀態/條件)
- 如果狀態位被設置為調試忙(10b),啟動加載程序還沒有讀取被JTAG主機移入到DR中的前一數值。這也表明,移出的8位數據沒有意義,因為啟動加載程序還沒有執行完命令。接收到該數值后,JTAG主機必須以前一發送的字節值重新裝入DR,這樣,啟動加載程序可以訪問它。正確執行這一操作的狀態順序如下。
- 在Shift-DR狀態,將最后一個比特移入到DR中,轉換到Exit1-DR之后,JTAG主機應檢查兩個狀態位。
- 如果接收到調試忙值,轉換到Pause-DR狀態,從這里到Exit2-DR,然后再次返回Shift-DR。重新裝入前一DR值(這次不是移位的數值),然后通過Exit1-DR和Update-DR,忽略第二次通過的狀態位值。
- 延遲較短的一段時間(取決于所執行的命令),重試字節傳送。
- 如果狀態位被設置為調試有效(11b)值,表明啟動加載程序讀取了移入的最后字節,已經裝入了應答字節。移出的8位數值含有有效數據。
;============================================================================== ;= ;= sendCommand ;= ;= Transmits a loader command by shifting bytes through DR. ;= ;= Inputs : DP[0] - Points to area of RAM which stores input bytes ;= for command and which will be filled with output. ;= LC[1] - Number of bytes to transmit/receive ;= Outputs : C - Set on JTAG communication error ;= Destroys : AP, APC, A[0], A[1], A[2], A[15], PSW, LC[0] ;= sendCommand: move APC, #80h ; Acc => A[0], turn off auto inc/dec push LC[1] call waitForPrompt pop LC[1] jump C, sendCommand_fail move Acc, @DP[0] ; Read first byte to transmit call shiftDR push Acc move Acc, A[1] cmp #3 ; Should be valid status since we had a prompt pop Acc jump NE, sendCommand_fail move @DP[0], Acc ; Store first received byte move NUL, @DP[0]++ ; Increment data pointer djnz LC[1], sendCommand_loop jump sendCommand_pass sendCommand_loop: move A[2], #10 ; Number of retries allowed sendCommand_retry: move Acc, @DP[0] ; Get next byte to transmit call shiftDR_next push Acc move Acc, A[1] cmp #3 pop Acc jump NE, sendCommand_stall move @DP[0], Acc ; Store received byte move NUL, @DP[0]++ ; Increment data pointer djnz LC[1], sendCommand_loop jump sendCommand_pass sendCommand_stall: move LC[0], #8000 ; About a millisecond djnz LC[0], $ move Acc, A[2] sub #1 jump NZ, sendCommand_retry jump sendCommand_fail
加載程序提供的功能
MAXQ微控制器的啟動加載程序功能一般采用共享模式,這意味著器件之間很多命令和狀態代碼都是相同的。不同器件根據內部程序存儲器結構和其他要求,可以采用不同的啟動加載程序命令子集。關于這方面的詳細信息,請參考您正在使用的MAXQ微控制器用戶指南附錄(English only)。對于這一情況,可以參考MAXQ2000用戶指南附錄(English only)中"在系統編程"一節的啟動加載程序命令。對于其他的MAXQ啟動加載程序,MAXQ2000啟動加載程序提供的命令被劃分成從0到15的命令集。每一命令以命令字節開始,它包括命令集(前四個比特)以及命令專用數(后四個比特),如表5所示。作為一般規則,命令集0的命令本質上用于提供信息,所有器件均采用它;其他命令集可選。為確定某一MAXQ器件支持的命令集,請參考器件文檔。命令集0的命令05h (獲得支持的命令)返回一個位掩碼,說明啟動加載程序支持的其他命令集。
MAXQ2000支持以下的啟動加載程序命令集。
- 命令集0—信息和狀態。該集的命令可用于獲得MAXQ器件的基本信息,包括ROM/啟動加載程序的標識和版本,最近命令的結果(狀態碼),程序和數據存儲器的容量等。該集還包括主機擦除命令,清除器件所有的程序和數據存儲器。
- 命令集1—裝入可變長度。該集中的這一命令可用于裝入程序(閃存)或者數據(RAM)存儲器。
- 命令集2—卸載可變長度。該集中的這一命令可用于讀取程序或者數據存儲器的內容。
- 命令集3—CRC可變長度。該集中的這一命令可用于獲得對某一范圍程序或者數據存儲器計算得到的CRC-16值。
- 命令集4—驗證可變長度。該集中的這一命令可用于驗證某一范圍的程序或者數據存儲器是否和JTAG主機提供的數據匹配。
- 命令集5—裝入和驗證可變長度。該集中的這一命令在一個命令中結合了裝入和驗證命令的功能。
- 命令集6—擦除可變長度。對于MAXQ2000,該命令可用于把數據RAM中的某一區域清零。
- 命令集7—擦除固定長度。對于MAXQ2000,該命令可用于擦除閃存程序存儲器中的每一頁面,而不必利用主機擦除命令將所有閃存一次擦除。
表5. MAXQ加載程序命令集
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Code | Family/Command |
0 | 0 | 0 | 0 | x | x | x | x | 0 x h | Family 0—Informational Commands |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00h | No Operation |
0 | 0 | 0 | 1 | 01h | Exit Loader | ||||
0 | 0 | 1 | 0 | 02h | Master Erase | ||||
0 | 0 | 1 | 1 | 03h | Password Match | ||||
0 | 1 | 0 | 0 | 04h | Get Status | ||||
0 | 1 | 0 | 1 | 05h | Get Supported Commands | ||||
0 | 1 | 1 | 0 | 06h | Get Code Memory Size | ||||
0 | 1 | 1 | 1 | 07h | Get Data Memory Size | ||||
1 | 0 | 0 | 0 | 08h | Get Loader Version | ||||
1 | 0 | 0 | 1 | 09h | Get Utility ROM Version | ||||
1 | 0 | 1 | 0 | 0Ah | Set Word/Byte Access Mode | ||||
1 | 1 | 0 | 1 | 0Dh | Get ID Information | ||||
0 | 0 | 0 | 1 | x | x | x | x | 1 x h | Family 1—Variable-Length Load |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 10h | Load Code Variable Length |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 11h | Load Data Variable Length |
0 | 0 | 1 | 0 | x | x | x | x | 2 x h | Family 2—Variable-Length Dump |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 20h | Dump Code Variable Length |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 21h | Dump Data Variable Length |
0 | 0 | 1 | 1 | x | x | x | x | 3 x h | Family 3—Variable-Length CRC |
0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 30h | CRC Code Variable Length |
0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 31h | CRC Data Variable Length |
0 | 1 | 0 | 0 | x | x | x | x | 4 x h | Family 4—Variable-Length Verify |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 40h | Verify Code Variable Length |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 41h | Verify Data Variable Length |
0 | 1 | 0 | 1 | x | x | x | x | 5 x h | Family 5—Variable-Length Load and Verify |
0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 50h | Load/Verify Code Variable Length |
0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 51h | Load/Verify Data Variable Length |
0 | 1 | 1 | 0 | x | x | x | x | 6 x h | Family 6—Variable-Length Erase |
0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 60h | Erase Code Variable Length |
0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 61h | Erase Data Variable Length |
0 | 1 | 1 | 1 | x | x | x | x | 7 x h | Family 7—Reserved (for expansion) |
1 | 0 | 0 | 0 | x | x | x | x | 8 x h | Family 8—Reserved (for expansion) |
1 | 0 | 0 | 1 | x | x | x | x | 9 x h | Family 9—Fixed-Length Load |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 90h | Load Code Fixed Length |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 91h | Load Data Fixed Length |
1 | 0 | 1 | 0 | x | x | x | x | A x h | Family A —Fixed-Length Dump |
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | A0h | Dump Code Fixed Length |
1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | A1h | Dump Data Fixed Length |
1 | 0 | 1 | 1 | x | x | x | x | B x h | Family B—Fixed-Length CRC |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | B0h | CRC Code Fixed Length |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | B1h | CRC Data Fixed Length |
1 | 1 | 0 | 0 | x | x | x | x | C x h | Family C—Fixed-Length Verify |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | C0h | Verify Code Fixed Length |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | C1h | Verify Data Fixed Length |
1 | 1 | 0 | 1 | x | x | x | x | D x h | Family D—Fixed-Length Load and Verify |
1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | D0h | Load/Verify Code Fixed Length |
1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | D1h | Load/Verify Data Fixed Length |
1 | 1 | 1 | 0 | x | x | x | x | E x h | Family E —Fixed-Length Erase |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | E0h | Erase Code Fixed Length |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | E1h | Erase Data Fixed Length |
1 | 1 | 1 | 1 | x | x | x | x | F x h | Family F—Reserved (device specific) |
識別JTAG從機控制器
啟動加載程序啟動并運行后,下一步是識別從機MAXQ微控制器。命令集0的命令0Dh (獲得ID信息)返回一個長度可變的ASCII字符串(以零結束),確定器件和程序ROM版本。作為演示的一部分,我們的實例程序獲得該信息,然后打印輸出至串口。用于實現該功能的例程是getBanner。
;============================================================================== ;= ;= getBanner ;= waitForPrompt ;= shiftDR ;= clock0, clock1, shift ;= ;= Executes command 0Dh to retrieve the ROM (device ID) banner and prints ;= the banner text out over the serial port. ;= ;= Inputs : None ;= Outputs : C - Set on JTAG communication error ;= Destroys : AP, APC, Acc, PSW, LC[0] ;= getBanner: call waitForPrompt jump C, getBanner_fail move Acc, #CMD_GET_ROM_BANNER call shiftDR move Acc, #00h call shiftDR getBanner_loop: move Acc, #00h call shiftDR cmp #0FFh ; The banner is ASCII, so receiving this character ; most likely indicates that the JTAG lines are ; floating high and that no device is connected jump E, getBanner_fail jump Z, getBanner_done call txChar jump getBanner_loop getBanner_done: call txNewline jump getBanner_pass getBanner_fail: move C, #1 ret getBanner_pass: move C, #0 ret
擦除程序存儲器
在對MAXQ2000包含的閃存程序存儲器進行編程之前,必須擦除它(設置為0FFFFh)。JTAG演示應用程序發送02h (主機擦除)啟動加載程序命令,指示啟動加載程序擦除所有的程序和數據存儲器,從而擦除閃存。該命令還清除了密碼鎖定位,使能所有支持的命令集。取決于MAXQ器件,這一02h (主機擦除)命令可能需要幾秒鐘的時間來完成。由于這是一個單字節命令,確定該命令什么時候完成的最簡單方法是不斷發送無操作(00h)命令,其后是1毫秒的延遲,直到啟動加載程序返回3Eh,表明命令已經完成。下面的 masterErase例程說明了這一方法。
;============================================================================== ;= ;= masterErase ;= ;= Executes command 02h (Master Erase) to clear all program and data memory. ;= ;= Inputs : None ;= Outputs : C - Set on JTAG communication error ;= Destroys : Acc, PSW, LC[0], LC[1] ;= masterErase: call waitForPrompt jump C, masterErase_fail move Acc, #CMD_MASTER_ERASE call shiftDR move Acc, #00h call shiftDR move LC[1], #5000 ; Number of retries before returning an error masterErase_loop: move Acc, #CMD_NOP call shiftDR cmp #3Eh jump E, masterErase_pass move LC[0], #8000 ; Delay for about a millisecond djnz LC[0], $ djnz LC[1], masterErase_loop masterErase_pass: move C, #0 ret masterErase_fail: move C, #1 ret
重新獲得狀態信息
MasterErase (或者任何其他啟動加載程序命令)完成后,可利用04h (獲得狀態)命令來確定命令是否成功完成。獲得狀態命令返回兩個數據字節:一個字節含有狀態標志(說明密碼鎖定設置/解除設置、字/字節模式有效以及其他信息),第二個字節是單字節狀態碼。如果最后一條命令成功完成,狀態碼總是00h (無錯誤)。非零狀態碼指示有錯誤。MAXQ2000用戶指南附錄(English only)列出了所有的狀態碼;這里列出了幾個常見錯誤碼。
- 01h/02h—不支持命令集/無效命令。這些錯誤代碼通常指示JTAG主機出現通信干擾或者校準錯誤。如果對于某一命令代碼,JTAG主機發送的字節多于(或者少于)啟動加載程序預期的字節,啟動加載程序會把數據字節之一理解為新命令開始。
- 03h—密碼不匹配。這一錯誤代碼通常指示JTAG主機在沒有清除密碼鎖定之前,試圖使用受到密碼保護的命令(一般包括不在命令集0中的命令)。如果JTAG主機訪問的部分已經有裝入字節地址0010h – 001Fh的代碼,則會出現這一錯誤。在這種情況下,這一部分必須被主機擦除,或者使用密碼匹配命令(03h)來解鎖這一部分。
- 05h—驗證失敗。對于裝入/驗證或者驗證命令,驗證步驟失敗。通信干擾會導致這一錯誤,或者對以前已經編程過的閃存沒有擦除就進行重新編程也會出現這一錯誤。
將代碼裝入程序存儲器
為演示JTAG啟動加載程序的功能,演示應用程序需要通過JTAG連接,把代碼裝入到從機MAXQ2000中。在這個例子中,裝入的代碼是一個簡單例程,它啟動LCD控制器,在LCD顯示屏上顯示一個4位數。裝入MAXQ2000的代碼基于下面的簡單演示工程。
org 0 ljump main org 20h main: move LCRA, #03E0h ; xxx0001111100000 ; 00 - DUTY : Static ; 0111 - FRM : Frame freq ; 1 - LCCS : HFClk / 128 ; 1 - LRIG : Ground VADJ ; 00000 - LRA : RADJ = Min move LCFG, #0F3h ; 1111xx11 ; 1111 - PCF : All segments enabled ; 1 - OPM : Normal operation ; 1 - DPE : Display enabled move LCD0, #LCD_CHAR_0 move LCD1, #LCD_CHAR_0 move LCD2, #LCD_CHAR_0 move LCD3, #LCD_CHAR_2 move LCD4, #00h sjump $然而,由于我們是從演示應用程序中裝入代碼字節,而不是從硬件編碼的十六進制文件中裝入(當采用MTK或者MAX-IDE裝入代碼時會有這種情況),因此,演示應用程序會根據用戶輸入來修改裝入的應用程序。
在裝入代碼前,JTAG通信演示應用程序首先告訴用戶輸入一個4位十進制數,然后修改要裝入的應用程序,如下所示。
- LCD上顯示的數字是用戶輸入的4位數。
- 密碼區的前4個字節(從字地址010h開始)被設置為用戶輸入的4字符ASCII值。
;;;; ;;;; First load - LJUMP 0020h at start of program memory ;;;; move DP[0], #0 move @DP[0], #CMD_LOAD_CODE_VARIABLE move @++DP[0], #4 ; Length - 4 bytes move @++DP[0], #00h ; AddrL (byte address 0000h) move @++DP[0], #00h ; AddrH move @++DP[0], #000h ; 00 0B 20 0C - ljump 0020h move @++DP[0], #00Bh move @++DP[0], #020h move @++DP[0], #00Ch move @++DP[0], #000h ; Padding move @++DP[0], #000h ; Padding move @++DP[0], #55h move LC[1], DP[0] move DP[0], #0 nop call sendCommand nop jump C, main_failJTAG call getStatus jump C, main_failJTAG move Acc, A[3] ; Check that loader status is 00h (no error) jump NZ, main_failStatus以同樣的方式裝入其他兩個存儲器代碼塊。
驗證程序存儲器代碼
一旦裝入代碼后,有幾種方法來驗證是否正確裝入。- 沒有使用裝入代碼可變長度命令(10h),而是使用裝入和驗證代碼可變長度命令(50h)。后一命令結合了代碼裝入操作和驗證步驟。
- 或者,也可以調用驗證代碼可變長度命令(40h)來單獨進行驗證。
- 沒有讓啟動加載程序驗證裝入的代碼,而是使用卸載代碼可變長度(20h)命令驗證裝入的代碼是否匹配發送的數據,JTAG主機直接驗證裝入的數值。
從程序存儲器卸載代碼
裝入所有代碼后,JTAG演示的最后一步是讀回一個塊中的所有代碼。向啟動加載程序發送卸載代碼可變長度(20h)命令來完成這一讀操作。這一命令的參數是開始卸載的地址(讀),以及卸載的字節數。注意,對于所有的JTAG啟動加載程序命令,必須為每一讀回的字節發送一個字節。因此,這一命令需要大量的零填充字節,從程序存儲器讀取每一字節都需要一個。;;;; ;;;; Dump program code ;;;; move DP[0], #str_dumpCodeVariable call txString move DP[0], #0 move @DP[0], #CMD_DUMP_CODE_VARIABLE move @++DP[0], #1 ; Indicates single byte length (<256 bytes) move @++DP[0], #00h ; AddrL (byte address 0000h) move @++DP[0], #00h ; AddrH move @++DP[0], #128 ; Length - 128 bytes move LC[1], #128 main_loop1: move @++DP[0], #00h djnz LC[1], main_loop1 move @++DP[0], #000h ; Padding move @++DP[0], #000h ; Padding move @++DP[0], #55h move LC[1], DP[0] move DP[0], #0 nop call sendCommand nop jump C, main_failJTAG call getStatus jump C, main_failJTAG move Acc, A[3] ; Check that loader status is 00h (no error) jump NZ, main_failStatus讀取這些代碼字節后,JTAG演示應用程序通過串口以十六進制格式輸出這些代碼字節。
退出啟動加載程序
單字節命令集0中的命令01h (退出啟動加載程序)導致啟動加載程序完成操作,并退出,如下所示。- 啟動加載程序啟動內部復位,把SPE和PSS位清零,復位微控制器。
- 微控制器退出復位,開始執行程序ROM的8000h。
- 現在SPE已經清為零,程序ROM代碼導致執行開始于地址0000h的用戶應用程序。
;;;; ;;;; Exit loader mode and allow program code to execute ;;;; call waitForPrompt move Acc, #CMD_EXIT_LOADER call shiftDR move Acc, #00h call shiftDR move Acc, #00h call shiftDR move Acc, #00h call shiftDR
操作演示
需要下面的硬件和軟件來運行JTAG啟動加載程序演示。硬件
- 兩塊MAXQ2000評估板(MAXQ2000-K00 REV B);一塊評估板用作主機MAXQ2000板,另一塊用作從機MAXQ2000板。
- MAXQ2000 LCD子卡(MAXQ2000-K01 REV B)
- 兩條2 x 5 JTAG接口電纜(含在MAXQ2000評估套件中)
- 串口至JTAG接口板(MAXQJTAG-001 REV B)
- DB9直通串行電纜
- 兩個5V穩壓(±5%)直流墻插電源,中心正極,CUI公司。DPR050030-P6或者等效電源。
- 兩個HC49US 8.00MHz晶振
- 2 x 5 0.100英寸引腳插座
- JTAG演示軟件包
- http://files.dalsemi.com/microcontroller/app_note_software/an4012_sw.zip
- MAXQ的MAX-IDE開發環境
- http://files.dalsemi.com/microcontroller/maxq/dev_tool_software/MAX-IDE/MAX-IDE.zip
- MAXQ的微控制器工具包(MTK)
- http://files.dalsemi.com/microcontroller/dev_tool_software/mtk/
- 如果還沒有安裝MAX-IDE,按照MAXQ2000評估套件中的文檔說明進行下載并安裝。
- 如果還沒有安裝MTK,按照MAXQ2000評估套件中的文檔說明進行下載并安裝。
- 連接LCD子卡和從機MAXQ2000板的J3插座,如前面的圖1所示。LCD子卡應固定在MAXQ2000評估板的上部。
- 在兩塊MAXQ2000評估板(在Y1)上安裝8.00MHz晶振。
- 在主機MAXQ2000板的原型區安裝2 x 5 JTAG插座,引腳連接至主機MAXQ2000引腳,如表1所列。
- 配置串口至JTAG板以及兩塊MAXQ2000評估板上的跳線和DIP開關,如表2所列。
- 使用DB9串行電纜連接PC的COM1口和串口至JTAG板的J1。
- 將第一個5V電源連接至串口至JTAG板的J2。
- 將第二個5V電源連接至從機MAXQ2000評估板的J1。
- 使用第一條JTAG電纜,連接串口至JTAG板的P2和主機MAXQ2000板的J4。紅色線應連接兩個JTAG插座的引腳1。
- 使用第二條JTAG電纜,連接主機MAXQ2000板原型區的JTAG插座和從機MAXQ2000板的J4。紅色線應連接兩個JTAG插座的引腳1。
- 下載JTAG演示軟件包,把它解壓縮到工作路徑中。
- 啟動MAX-IDE。
- 打開兩路5V電源。
- 從菜單中選擇Project Open Project ,選擇maxqjtag.prj工程文件,打開它。
- 從菜單中選擇Debug Make。應出現"Build Successful"消息。
- 從菜單中選擇Debug Run。應出現一連串的"Loading"消息,隨后是"Done"。
- 從菜單中選擇Debug Stop。
- 關閉MAX-IDE。
- 關掉電源。
- 在斷電情況下,從串口至JTAG板斷開DB9串行電纜。
- DB9電纜連接至主機MAXQ2000板的J5。
- 啟動MTK。在起始對話框中選擇"Dumb Terminal"。
- 從菜單中選擇Options Configure Serial Port。在對話框中,設置Port為COM1,Speed為9600波特率。
- 從菜單中選擇Target Open COM1 at 9600 baud。
- 打開電源。
圖5. 演示應用程序,串口提示符
現在輸入一個4位十進制數;不需要隨后按下回車鍵。演示應用程序會完成剩下的操作(主機擦除、裝入代碼和卸載代碼),并輸出結果,以及從程序存儲器中卸載的十六進制字節值,如圖6所示。
圖6. 演示應用程序,串口輸出
評論
查看更多