簡(jiǎn)介
具有可在線編程的程序存儲(chǔ)器(例如MAXQ2000和MAXQ3210)的MAXQ微控制器一般還提供基于ROM的啟動(dòng)加載程序,利用微控制器的JTAG兼容調(diào)試端口,實(shí)現(xiàn)程序存儲(chǔ)器的加載。盡管不同的器件有不同的JTAG啟動(dòng)加載程序功能,但是通常都包括程序和數(shù)據(jù)存儲(chǔ)器寫、讀、驗(yàn)證和擦除等命令。有的器件為啟動(dòng)加載程序提供其他接口(例如,串口或者SPI?接口),而JTAG接口是最常用的,原因有兩個(gè)。第一,JTAG接口支持在線調(diào)試功能,第二,最終用戶應(yīng)用程序并沒有充分發(fā)揮JTAG接口的功能(與串口不同)。一旦加載程序代碼后,可選擇的加密機(jī)制限制了對(duì)啟動(dòng)加載程序的訪問(wèn),或在線調(diào)試。關(guān)于每個(gè)MAXQ器件功能的詳細(xì)信息,請(qǐng)參考產(chǎn)品說(shuō)明,包括數(shù)據(jù)資料和用戶指南等。本應(yīng)用筆記涉及到實(shí)現(xiàn)MAXQ2000 JTAG啟動(dòng)加載程序主機(jī)的基本步驟。這些步驟包括JTAG端口接口,測(cè)試訪問(wèn)端口(TAP)控制器通信,激活啟動(dòng)加載程序模式,向基于ROM的啟動(dòng)加載程序發(fā)送命令等。由于所有MAXQ器件的JTAG端口工作情況一般相同,MAXQ啟動(dòng)加載程序采用共享命令集工作,因此,在實(shí)現(xiàn)MAXQ微控制器JTAG啟動(dòng)加載程序主機(jī)時(shí)可以參考本應(yīng)用筆記涉及到的大部分主題(以及大部分實(shí)例代碼)。
除了串口,應(yīng)用筆記并沒有使用MAXQ2000的特殊功能。這表明,這里的實(shí)例代碼很容易重新用于程序存儲(chǔ)器空間足夠大的任何MAXQ20器件。代碼以MAXQ匯編語(yǔ)言編寫,采用MAX-IDE開發(fā)環(huán)境編譯??梢?a href="http://www.brongaenegriffin.com/soft/special/" target="_blank">下載這些代碼。
硬件設(shè)置
采用一對(duì)MAXQ2000評(píng)估(EV)板來(lái)開發(fā)本應(yīng)用筆記的實(shí)例代碼。需要兩塊MAXQ2000評(píng)估板執(zhí)行這里的軟件。一個(gè)MAXQ2000 (JTAG主機(jī))運(yùn)行實(shí)例代碼;第二個(gè)MAXQ2000用作JTAG從機(jī),由主機(jī)對(duì)它重新編程。兩個(gè)MAXQ2000微控制器都采用了標(biāo)準(zhǔn)8.00MHz晶振。在原型區(qū)安裝一個(gè)2 x 5引腳插座對(duì)主機(jī)MAXQ2000評(píng)估板進(jìn)行改動(dòng),原型區(qū)提供JTAG電纜主機(jī)側(cè)連接。插座的引腳符合標(biāo)準(zhǔn)MAXQ JTAG插座布局,按照表1所示進(jìn)行連接。
表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 |
不需要對(duì)從機(jī)MAXQ2000評(píng)估板進(jìn)行改動(dòng)。按照上面的說(shuō)明在主機(jī)MAXQ2000評(píng)估板的原型區(qū)安裝2 x 5 JTAG插座。然后,將兩塊評(píng)估板連接起來(lái);主機(jī)評(píng)估板原型區(qū)的2 x 5 JTAG插座和從機(jī)評(píng)估板的標(biāo)準(zhǔn)JTAG插座(J4)之間連接標(biāo)準(zhǔn)2 x 5 JTAG電纜(這種JTAG一般用于連接串口至JTAG板和MAXQ評(píng)估板)。JTAG 2 x 5連接器含在MAXQ2000評(píng)估套件中。
為簡(jiǎn)化起見,沒有對(duì)主機(jī)評(píng)估板和從機(jī)評(píng)估板的JTAG電纜電源或者參考電壓連接進(jìn)行試驗(yàn)。而是設(shè)置兩塊評(píng)估板采用同一VDDIO電壓(大約3.6V)工作。這種設(shè)置保證了主機(jī)和從機(jī)MAXQ2000采用公共I/O電源電平工作。
從機(jī)評(píng)估板還在插座J3上安裝了LCD子卡(MAXQ2000-K01)。表2列出了兩塊電路板(以及串口至JTAG電路板)的跳線和DIP開關(guān)設(shè)置。注意:應(yīng)斷開未列出的所有跳線。圖1所示為最終設(shè)置。
表2. 電路板開關(guān)和跳線設(shè)置
| 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接口由四條信號(hào)線組成,用于測(cè)試訪問(wèn)端口(TAP)控制器的信息輸入和輸出。TAP控制器支持對(duì)MAXQ啟動(dòng)加載程序的訪問(wèn),提供在線調(diào)試功能(注意,調(diào)試主機(jī)的實(shí)現(xiàn)和啟動(dòng)加載程序主機(jī)的實(shí)現(xiàn)類似,但是已經(jīng)超出了本應(yīng)用筆記的范圍)。表3對(duì)四條JTAG信號(hào)線進(jìn)行了說(shuō)明。表3. JTAG接口信號(hào)
| 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. |
從技術(shù)上看,nRESET引腳并不是JTAG接口的組成部分。它含在JTAG電纜中,使JTAG主機(jī)能夠復(fù)位從機(jī)微控制器。重新設(shè)置從機(jī)微控制器是進(jìn)入啟動(dòng)加載程序模式需要的步驟,如果JTAG通信意外中斷,也需要重新設(shè)置從機(jī)微控制器。
JTAG接口是全雙工的,數(shù)據(jù)在TDI線上由主機(jī)送入從機(jī),同時(shí),數(shù)據(jù)在TDO線上由從機(jī)送入主機(jī)。從機(jī)在TCK上升沿對(duì)到達(dá)數(shù)據(jù)(在TDI和TMS上)進(jìn)行采樣,在TCK下降沿,數(shù)據(jù)在TDO上被驅(qū)動(dòng)輸出至主機(jī)。對(duì)于到達(dá)和輸出數(shù)據(jù),最先傳送最低有效位。本應(yīng)用筆記簡(jiǎn)要介紹JTAG接口和TAP控制器,以解釋實(shí)例代碼的工作。關(guān)于這些特性的詳細(xì)討論,請(qǐng)參考MAXQ系列用戶指南(English only)的測(cè)試訪問(wèn)端口(TAP)、在線調(diào)試模式、在系統(tǒng)編程等章節(jié),公司網(wǎng)站上有該文檔。
TAP控制器通信
TAP控制器圍繞狀態(tài)機(jī)進(jìn)行構(gòu)建,如下面的圖2所示。TAP狀態(tài)機(jī)中有16個(gè)分立狀態(tài)。根據(jù)TMS信號(hào)值,在TCK的上升沿從一個(gè)狀態(tài)向下一個(gè)狀態(tài)轉(zhuǎn)變。例如,如果TAP控制器處于Select-DR-Scan狀態(tài),TCK出現(xiàn)了上升沿:- 如果TMS = 1,TAP控制器將轉(zhuǎn)換到Select-IR-Scan狀態(tài)。
- 如果TMS = 0,TAP控制器將轉(zhuǎn)換到Capture-DR狀態(tài)。
- 5個(gè)'1'轉(zhuǎn)換(保持TMS高電平,同步TCK 5個(gè)周期)總是使?fàn)顟B(tài)機(jī)回到Test-Logic-Reset,而不論起始狀態(tài)如何。這表明,如果不確定TAP控制器當(dāng)前的狀態(tài),或者在某些情況下JTAG主機(jī)和從機(jī)間的通信中斷,總是可以通過(guò)同步5個(gè)'1'轉(zhuǎn)換,使TAP控制器回到已知狀態(tài)。
- 即使TCK時(shí)鐘繼續(xù)運(yùn)行,也可以暫停JTAG通信,不確定地保持在Run-Test-Idle、Pause-DR或者Pause-IR狀態(tài),而不影響TAP控制器的狀態(tài)。

圖2. 測(cè)試訪問(wèn)端口(TAP)狀態(tài)機(jī)
TAP控制器的狀態(tài)機(jī)提供對(duì)兩個(gè)控制寄存器的訪問(wèn),而寄存器提供啟動(dòng)加載程序接口、調(diào)試接口以及其他功能。
- IR (指令寄存器)寬度總是3位。該寄存器可以用作指數(shù)寄存器,控制DR的功能(參見下面)。
- DR (數(shù)據(jù)寄存器)是TAP控制器中幾個(gè)寄存器的訪問(wèn)點(diǎn)。當(dāng)比特移入或者移出DR時(shí)實(shí)際訪問(wèn)的寄存器取決于IR當(dāng)前值。

圖3. TAP控制器中的寄存器訪問(wèn)
如圖3所示,DR根據(jù)IR值而指向三個(gè)內(nèi)部寄存器之一。
- 如果IR = 011b,TAP控制器處于Bypass模式。在這一模式下(這是TAP控制器的默認(rèn)模式),通過(guò)TDO,移入到DR (通過(guò)TDI)的數(shù)據(jù)被直接移回送出。通過(guò)TAP控制器移動(dòng)數(shù)據(jù)并沒有改變內(nèi)部寄存器。
- 設(shè)置IR = 100b,使TAP控制器處于System Programming模式。在這種模式下,移入DR中的數(shù)據(jù)被移入到3位系統(tǒng)編程寄存器中。該寄存器(也可以通過(guò)MAXQ微控制器ICDF寄存器的[3:1]位進(jìn)行訪問(wèn))控制MAXQ復(fù)位后進(jìn)入正常程序執(zhí)行模式還是啟動(dòng)加載程序模式。如果使能啟動(dòng)加載程序模式,它還控制啟動(dòng)加載程序使用哪一接口(JTAG、串口或者SPI)。
- 設(shè)置IR = 010b,使TAP控制器進(jìn)入Debug模式。在這一模式下,移入DR的數(shù)據(jù)被移入到內(nèi)部10位調(diào)試寄存器中,可以被啟動(dòng)加載程序讀取。啟動(dòng)加載程序輸出的數(shù)據(jù)也通過(guò)該寄存器,在TDO上被移回送出(以及兩個(gè)狀態(tài)位)。該寄存器被用于啟動(dòng)加載程序模式和在線調(diào)試模式時(shí)的數(shù)據(jù)傳送。
控制JTAG端口和復(fù)位線
從機(jī)MAXQ2000 (TMS, TCK, TDO和TDI) JTAG/TAP端口的四條線以及nRESET線分別連接至主機(jī)MAXQ2000的一個(gè)端口引腳。控制JTAG接口的第一步是正確配置這些線。#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線工作在標(biāo)準(zhǔn)驅(qū)動(dòng)模式下。從主機(jī)角度看,TMS、TCK和TDI總是被驅(qū)動(dòng)為輸出,而TDO (由從機(jī)驅(qū)動(dòng))總是為輸入。JTAG線的方向固定,不是雙向的。nRESET線是特殊情況,被配置為主機(jī)側(cè)開漏輸出。通常,從機(jī)將自己的nRESET線拉至高電平,因此,主機(jī)只能將該線拉低(復(fù)位從機(jī)時(shí)),或者完全釋放它(在其他所有時(shí)間)。主機(jī)不應(yīng)將從機(jī)的nRESET線驅(qū)動(dòng)為高電平。
;============================================================================== ;= ;= 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來(lái)同步TMS線上的靜態(tài)0和1,使TAP控制器從一個(gè)狀態(tài)轉(zhuǎn)換到另一狀態(tài)。只要JTAG時(shí)鐘速率保持低于從機(jī)微控制器系統(tǒng)時(shí)鐘速率1/8的最大值,JTAG時(shí)鐘可以采用任何頻率。這里不需要考慮主機(jī)的系統(tǒng)時(shí)鐘速率;它不需要和從機(jī)系統(tǒng)時(shí)鐘速率相匹配。主機(jī)可以比從機(jī)運(yùn)行的快或者慢,而不會(huì)導(dǎo)致出現(xiàn)JTAG通信問(wèn)題。
由于這一例子中的從機(jī)MAXQ2000安裝了8MHz時(shí)鐘晶振,主機(jī)能夠驅(qū)動(dòng)JTAG時(shí)鐘達(dá)到1MHz,而不會(huì)出現(xiàn)問(wèn)題。對(duì)于這個(gè)例子,100kHz JTAG時(shí)鐘足夠了。
#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利用這兩個(gè)例程,我們可以增加另一個(gè)例程來(lái)初始化TAP控制器,迫使它回到Test-Logic-Reset狀態(tài)。注意Test-Logic-Reset狀態(tài),正如其名稱的含義,它對(duì)TAP邏輯進(jìn)行徹底復(fù)位,包括確定啟動(dòng)加載程序是否使能以及啟動(dòng)加載程序使用哪一接口位(SPE和PSS[1:0])。因此,一旦進(jìn)入啟動(dòng)加載程序模式,設(shè)置TAP控制器為Test-Logic-Reset,對(duì)器件進(jìn)行復(fù)位,退出啟動(dòng)加載程序模式。演示應(yīng)用程序中使用的JTAG例程(除了testLogicReset本身之外)都假定TAP控制器在例程啟動(dòng)時(shí)處于Run-Test-Idle狀態(tài)。在JTAG通信期間,TAP控制器在不同狀態(tài)間轉(zhuǎn)換;例程最后,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狀態(tài)機(jī)向下轉(zhuǎn)換到Shift-IR狀態(tài),同步輸入一個(gè)新的3位數(shù)值,將數(shù)值裝入TAP控制器的IR。在進(jìn)入U(xiǎn)pdate-IR狀態(tài)之前,該數(shù)值并沒有實(shí)際從移位寄存器復(fù)制到指令寄存器中。對(duì)于所有的JTAG移位寄存器操作,隨著新數(shù)值的移入,寄存器的當(dāng)前內(nèi)容被移出(由TDO)。但是,移出的數(shù)值總是固定的(001b);這是由JTAG標(biāo)準(zhǔn)在測(cè)試JTAG接口功能時(shí)決定的。
比特移入和移出移位寄存器的過(guò)程(IR或者DR)是一樣的;TAP狀態(tài)機(jī)必須分別處于Shift-IR或者Shift-DR狀態(tài),TAP控制器在每個(gè)TCK周期的上升沿對(duì)輸入比特(在TDI)進(jìn)行采樣,而在TCK周期下降沿驅(qū)動(dòng)輸出比特(在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對(duì)于傳送的每一位,除了最后一位之外,TMS必須保持低電平。這非常重要,因?yàn)楫?dāng)每一位移入和移出時(shí),狀態(tài)機(jī)保持在Shift-IR或者Shift-DR狀態(tài)。在最后一個(gè)比特周期,TMS必須被驅(qū)動(dòng)為高電平,這樣,隨著最后一位的輸入和輸出,TAP控制器將進(jìn)入Exit1-DR或者Exit1-IR狀態(tài)。
作為一個(gè)例子,在表4中,JTAG主機(jī)將數(shù)值100b (系統(tǒng)編程模式)移入到IR寄存器中。IR寄存器開始設(shè)置旁路值011b;TAP控制器最初為Run-Test-Idle狀態(tài)。如下面的圖4所示,比特以最低有效位在前、最高有效位在后移入(移出)TAP控制器。因此,在第一個(gè)移位周期,新數(shù)值的第0位被移入,舊數(shù)值的第0位被移出。
表4. 指令寄存器移位實(shí)例
| 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 |
下面是執(zhí)行這一操作的例程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數(shù)據(jù)寄存器
數(shù)值移入或者移出TAP控制器DR的操作與裝入/卸載IR的方式相似。通常,只有當(dāng)IR被設(shè)置為兩個(gè)數(shù)值之一時(shí)才能進(jìn)行這一操作:100b (使TAP控制器進(jìn)入系統(tǒng)編程模式)或者010b (使TAP控制器進(jìn)入調(diào)試模式)。激活系統(tǒng)編程模式后,裝入和卸載DR寄存器的操作如下。
- DR寄存器移入和移出寬度為3比特。所有三個(gè)比特都代表有效數(shù)據(jù)。
- 當(dāng)?shù)竭_(dá)Update-DR狀態(tài)時(shí),送入DR寄存器的數(shù)值被復(fù)制到從機(jī)微控制器的內(nèi)部系統(tǒng)編程寄存器中。這三個(gè)比特的用法如下。
- 從機(jī)微控制器可訪問(wèn)第0位(讀/寫),它作為寄存器位ICDF.1 (SPE),也被稱為系統(tǒng)編程使能位。復(fù)位后,程序ROM檢查該位,確定應(yīng)進(jìn)入啟動(dòng)加載程序模式(SPE = 1)還是正常程序執(zhí)行模式(SPE = 0)。
- 從機(jī)微控制器可訪問(wèn)第1位和第2位(讀/寫),它作為寄存器位ICDF.2-3 (PSS0-PSS1),也被稱為編程源選擇位。對(duì)于能夠?yàn)閱?dòng)加載程序提供多個(gè)接口的微控制器,例如MAXQ2000,這些位用于當(dāng)SPE = 1時(shí)應(yīng)選擇哪一啟動(dòng)加載程序接口。當(dāng)SPE = 0 (正常程序執(zhí)行模式)時(shí),這些位的設(shè)置不起作用。
- DR寄存器傳送出去的數(shù)值是系統(tǒng)編程寄存器以前的數(shù)值(當(dāng)進(jìn)入Capture-DR狀態(tài)后,鎖存到移位寄存器中)。
- DR寄存器移入和移出寬度為10比特。對(duì)于移出數(shù)據(jù),所有10個(gè)比特都代表有效數(shù)據(jù)(8個(gè)數(shù)據(jù)位和2個(gè)狀態(tài)位)。對(duì)于移入數(shù)據(jù),只使用了8個(gè)數(shù)據(jù)位;沒有使用兩個(gè)狀態(tài)位。
- 然后,將移入DR寄存器的高8位卸載,作為啟動(dòng)加載程序命令的一部分,被啟動(dòng)加載程序(從程序ROM中運(yùn)行)讀取。
- 移出DR寄存器的10個(gè)比特含有8位由啟動(dòng)加載程序裝入的數(shù)值(作為命令輸出的一部分),以及由TAP控制器設(shè)置的兩個(gè)狀態(tài)信息位。
;============================================================================== ;= ;= 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
進(jìn)入JTAG程序加載模式
需要按照以下步驟使MAXQ2000進(jìn)入JTAG啟動(dòng)加載程序模式。- 初始化TAP控制器,重新設(shè)置它,進(jìn)入Test-Logic-Reset狀態(tài)。
- 設(shè)置指令寄存器(IR)為100b,使能系統(tǒng)編程模式。
- 設(shè)置數(shù)據(jù)寄存器(DR)為001b。這使得SPE(系統(tǒng)編程使能)位為1,使能啟動(dòng)加載程序,設(shè)置PSS[1:0] (編程源選擇)位為00b,選擇JTAG接口。
- 保持nRESET低電平,復(fù)位MAXQ2000。
- 釋放nRESET。這導(dǎo)致MAXQ2000指向程序ROM (8000h)中的標(biāo)準(zhǔn)復(fù)位點(diǎn)。程序ROM代碼將檢查SPE和PSS位值,相應(yīng)地激活JTAG啟動(dòng)加載程序。在這一點(diǎn),啟動(dòng)加載程序運(yùn)行,準(zhǔn)備接收J(rèn)TAG命令。
- 設(shè)置指令寄存器(IR)為010b,使能調(diào)試模式。該模式用于和JTAG啟動(dòng)加載程序或者調(diào)試引擎進(jìn)行通信;在這一例子中,我們將使用該模式和啟動(dòng)加載程序進(jìn)行通信。
- 10位數(shù)據(jù)移位通過(guò)DR,開始向JTAG啟動(dòng)加載程序發(fā)送命令。
#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 ...
與加載程序通信
一旦啟動(dòng)加載程序運(yùn)行,程序ROM中的啟動(dòng)加載程序代碼讀取內(nèi)部寄存器的命令代碼,命令代碼由DR移位寄存器裝入。程序ROM還把結(jié)果數(shù)據(jù)寫入另一內(nèi)部寄存器,由JTAG主機(jī)通過(guò)DR寄存器移出。通過(guò)這種方式,啟動(dòng)加載程序代碼和JTAG主機(jī)交換信息。然而,啟動(dòng)加載程序代碼和JTAG主機(jī)并不同步。只要JTAG時(shí)鐘保持低于MAXQ系統(tǒng)時(shí)鐘1/8的最大值,由于JTAG是同步接口,因此,兩路時(shí)鐘的確切值并不影響通信。但是,MAXQ系統(tǒng)時(shí)鐘速率以及接收到的啟動(dòng)加載程序命令特性將決定啟動(dòng)加載程序接收命令和發(fā)送回應(yīng)之間的延時(shí)。例如,1MHz運(yùn)行的MAXQ2000響應(yīng)某一啟動(dòng)加載程序命令的時(shí)間要比10MHz的MAXQ2000時(shí)間長(zhǎng),即使兩個(gè)微控制器都可以采用100kHz的JTAG時(shí)鐘進(jìn)行通信。只是讀并返回信息的命令,例如返回ROM標(biāo)志ID的命令以及從程序存儲(chǔ)器讀取的命令,花費(fèi)的時(shí)間也要少于編程閃存操作等命令。
通過(guò)JTAG接口傳送的數(shù)據(jù)沒有被緩沖。如果在前一命令被讀取之前,發(fā)送了另一10位命令,前一命令的結(jié)果丟失。ROM代碼和TAP控制器保證前一數(shù)據(jù)被JTAG主機(jī)卸載前,啟動(dòng)加載程序不會(huì)發(fā)送其他數(shù)據(jù),但反方向還是需要同步。JTAG主機(jī)需要通過(guò)某種方式知道移入DR的前一字節(jié)是否已經(jīng)被啟動(dòng)加載程序讀取了。這樣,JTAG主機(jī)能夠知道什么時(shí)候發(fā)送下一字節(jié)。采用的方法是利用TAP控制器發(fā)送的其他兩個(gè)狀態(tài)位,以及啟動(dòng)加載程序輸出的每個(gè)8位字節(jié)。

圖4. 通過(guò)DR的移位數(shù)據(jù)和狀態(tài)位
2x5 如上面的圖4所示,在TAP調(diào)試模式下,移入和移出DR的數(shù)據(jù)包括8個(gè)數(shù)據(jù)位(第2位到第9位)和兩個(gè)狀態(tài)位(第0位和第1位)。當(dāng)JTAG主機(jī)移入數(shù)據(jù)時(shí),只使用8個(gè)數(shù)據(jù)位。TAP控制器沒有使用的兩個(gè)狀態(tài)位(也必須被移入),可以被設(shè)置為零,或者任何其他值。
在TAP控制器移出的10位數(shù)值中,兩個(gè)狀態(tài)位提供啟動(dòng)加載程序或者調(diào)試引擎的狀態(tài)信息。當(dāng)啟動(dòng)加載程序運(yùn)行時(shí),一般只能達(dá)到最后兩個(gè)狀態(tài)(調(diào)試忙或者調(diào)試有效),這是因?yàn)槠渌麅蓚€(gè)狀態(tài)值不會(huì)出現(xiàn)在啟動(dòng)加載程序模式中。(參見圖4中的狀態(tài)/條件)
- 如果狀態(tài)位被設(shè)置為調(diào)試忙(10b),啟動(dòng)加載程序還沒有讀取被JTAG主機(jī)移入到DR中的前一數(shù)值。這也表明,移出的8位數(shù)據(jù)沒有意義,因?yàn)閱?dòng)加載程序還沒有執(zhí)行完命令。接收到該數(shù)值后,JTAG主機(jī)必須以前一發(fā)送的字節(jié)值重新裝入DR,這樣,啟動(dòng)加載程序可以訪問(wèn)它。正確執(zhí)行這一操作的狀態(tài)順序如下。
- 在Shift-DR狀態(tài),將最后一個(gè)比特移入到DR中,轉(zhuǎn)換到Exit1-DR之后,JTAG主機(jī)應(yīng)檢查兩個(gè)狀態(tài)位。
- 如果接收到調(diào)試忙值,轉(zhuǎn)換到Pause-DR狀態(tài),從這里到Exit2-DR,然后再次返回Shift-DR。重新裝入前一DR值(這次不是移位的數(shù)值),然后通過(guò)Exit1-DR和Update-DR,忽略第二次通過(guò)的狀態(tài)位值。
- 延遲較短的一段時(shí)間(取決于所執(zhí)行的命令),重試字節(jié)傳送。
- 如果狀態(tài)位被設(shè)置為調(diào)試有效(11b)值,表明啟動(dòng)加載程序讀取了移入的最后字節(jié),已經(jīng)裝入了應(yīng)答字節(jié)。移出的8位數(shù)值含有有效數(shù)據(jù)。
;============================================================================== ;= ;= 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微控制器的啟動(dòng)加載程序功能一般采用共享模式,這意味著器件之間很多命令和狀態(tài)代碼都是相同的。不同器件根據(jù)內(nèi)部程序存儲(chǔ)器結(jié)構(gòu)和其他要求,可以采用不同的啟動(dòng)加載程序命令子集。關(guān)于這方面的詳細(xì)信息,請(qǐng)參考您正在使用的MAXQ微控制器用戶指南附錄(English only)。對(duì)于這一情況,可以參考MAXQ2000用戶指南附錄(English only)中"在系統(tǒng)編程"一節(jié)的啟動(dòng)加載程序命令。對(duì)于其他的MAXQ啟動(dòng)加載程序,MAXQ2000啟動(dòng)加載程序提供的命令被劃分成從0到15的命令集。每一命令以命令字節(jié)開始,它包括命令集(前四個(gè)比特)以及命令專用數(shù)(后四個(gè)比特),如表5所示。作為一般規(guī)則,命令集0的命令本質(zhì)上用于提供信息,所有器件均采用它;其他命令集可選。為確定某一MAXQ器件支持的命令集,請(qǐng)參考器件文檔。命令集0的命令05h (獲得支持的命令)返回一個(gè)位掩碼,說(shuō)明啟動(dòng)加載程序支持的其他命令集。
MAXQ2000支持以下的啟動(dòng)加載程序命令集。
- 命令集0—信息和狀態(tài)。該集的命令可用于獲得MAXQ器件的基本信息,包括ROM/啟動(dòng)加載程序的標(biāo)識(shí)和版本,最近命令的結(jié)果(狀態(tài)碼),程序和數(shù)據(jù)存儲(chǔ)器的容量等。該集還包括主機(jī)擦除命令,清除器件所有的程序和數(shù)據(jù)存儲(chǔ)器。
- 命令集1—裝入可變長(zhǎng)度。該集中的這一命令可用于裝入程序(閃存)或者數(shù)據(jù)(RAM)存儲(chǔ)器。
- 命令集2—卸載可變長(zhǎng)度。該集中的這一命令可用于讀取程序或者數(shù)據(jù)存儲(chǔ)器的內(nèi)容。
- 命令集3—CRC可變長(zhǎng)度。該集中的這一命令可用于獲得對(duì)某一范圍程序或者數(shù)據(jù)存儲(chǔ)器計(jì)算得到的CRC-16值。
- 命令集4—驗(yàn)證可變長(zhǎng)度。該集中的這一命令可用于驗(yàn)證某一范圍的程序或者數(shù)據(jù)存儲(chǔ)器是否和JTAG主機(jī)提供的數(shù)據(jù)匹配。
- 命令集5—裝入和驗(yàn)證可變長(zhǎng)度。該集中的這一命令在一個(gè)命令中結(jié)合了裝入和驗(yàn)證命令的功能。
- 命令集6—擦除可變長(zhǎng)度。對(duì)于MAXQ2000,該命令可用于把數(shù)據(jù)RAM中的某一區(qū)域清零。
- 命令集7—擦除固定長(zhǎng)度。對(duì)于MAXQ2000,該命令可用于擦除閃存程序存儲(chǔ)器中的每一頁(yè)面,而不必利用主機(jī)擦除命令將所有閃存一次擦除。
表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) |
識(shí)別JTAG從機(jī)控制器
啟動(dòng)加載程序啟動(dòng)并運(yùn)行后,下一步是識(shí)別從機(jī)MAXQ微控制器。命令集0的命令0Dh (獲得ID信息)返回一個(gè)長(zhǎng)度可變的ASCII字符串(以零結(jié)束),確定器件和程序ROM版本。作為演示的一部分,我們的實(shí)例程序獲得該信息,然后打印輸出至串口。用于實(shí)現(xiàn)該功能的例程是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
擦除程序存儲(chǔ)器
在對(duì)MAXQ2000包含的閃存程序存儲(chǔ)器進(jìn)行編程之前,必須擦除它(設(shè)置為0FFFFh)。JTAG演示應(yīng)用程序發(fā)送02h (主機(jī)擦除)啟動(dòng)加載程序命令,指示啟動(dòng)加載程序擦除所有的程序和數(shù)據(jù)存儲(chǔ)器,從而擦除閃存。該命令還清除了密碼鎖定位,使能所有支持的命令集。取決于MAXQ器件,這一02h (主機(jī)擦除)命令可能需要幾秒鐘的時(shí)間來(lái)完成。由于這是一個(gè)單字節(jié)命令,確定該命令什么時(shí)候完成的最簡(jiǎn)單方法是不斷發(fā)送無(wú)操作(00h)命令,其后是1毫秒的延遲,直到啟動(dòng)加載程序返回3Eh,表明命令已經(jīng)完成。下面的 masterErase例程說(shuō)明了這一方法。
;============================================================================== ;= ;= 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
重新獲得狀態(tài)信息
MasterErase (或者任何其他啟動(dòng)加載程序命令)完成后,可利用04h (獲得狀態(tài))命令來(lái)確定命令是否成功完成。獲得狀態(tài)命令返回兩個(gè)數(shù)據(jù)字節(jié):一個(gè)字節(jié)含有狀態(tài)標(biāo)志(說(shuō)明密碼鎖定設(shè)置/解除設(shè)置、字/字節(jié)模式有效以及其他信息),第二個(gè)字節(jié)是單字節(jié)狀態(tài)碼。如果最后一條命令成功完成,狀態(tài)碼總是00h (無(wú)錯(cuò)誤)。非零狀態(tài)碼指示有錯(cuò)誤。MAXQ2000用戶指南附錄(English only)列出了所有的狀態(tài)碼;這里列出了幾個(gè)常見錯(cuò)誤碼。
- 01h/02h—不支持命令集/無(wú)效命令。這些錯(cuò)誤代碼通常指示JTAG主機(jī)出現(xiàn)通信干擾或者校準(zhǔn)錯(cuò)誤。如果對(duì)于某一命令代碼,JTAG主機(jī)發(fā)送的字節(jié)多于(或者少于)啟動(dòng)加載程序預(yù)期的字節(jié),啟動(dòng)加載程序會(huì)把數(shù)據(jù)字節(jié)之一理解為新命令開始。
- 03h—密碼不匹配。這一錯(cuò)誤代碼通常指示JTAG主機(jī)在沒有清除密碼鎖定之前,試圖使用受到密碼保護(hù)的命令(一般包括不在命令集0中的命令)。如果JTAG主機(jī)訪問(wèn)的部分已經(jīng)有裝入字節(jié)地址0010h – 001Fh的代碼,則會(huì)出現(xiàn)這一錯(cuò)誤。在這種情況下,這一部分必須被主機(jī)擦除,或者使用密碼匹配命令(03h)來(lái)解鎖這一部分。
- 05h—驗(yàn)證失敗。對(duì)于裝入/驗(yàn)證或者驗(yàn)證命令,驗(yàn)證步驟失敗。通信干擾會(huì)導(dǎo)致這一錯(cuò)誤,或者對(duì)以前已經(jīng)編程過(guò)的閃存沒有擦除就進(jìn)行重新編程也會(huì)出現(xiàn)這一錯(cuò)誤。
將代碼裝入程序存儲(chǔ)器
為演示JTAG啟動(dòng)加載程序的功能,演示應(yīng)用程序需要通過(guò)JTAG連接,把代碼裝入到從機(jī)MAXQ2000中。在這個(gè)例子中,裝入的代碼是一個(gè)簡(jiǎn)單例程,它啟動(dòng)LCD控制器,在LCD顯示屏上顯示一個(gè)4位數(shù)。裝入MAXQ2000的代碼基于下面的簡(jiǎn)單演示工程。
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 $
然而,由于我們是從演示應(yīng)用程序中裝入代碼字節(jié),而不是從硬件編碼的十六進(jìn)制文件中裝入(當(dāng)采用MTK或者M(jìn)AX-IDE裝入代碼時(shí)會(huì)有這種情況),因此,演示應(yīng)用程序會(huì)根據(jù)用戶輸入來(lái)修改裝入的應(yīng)用程序。在裝入代碼前,JTAG通信演示應(yīng)用程序首先告訴用戶輸入一個(gè)4位十進(jìn)制數(shù),然后修改要裝入的應(yīng)用程序,如下所示。
- LCD上顯示的數(shù)字是用戶輸入的4位數(shù)。
- 密碼區(qū)的前4個(gè)字節(jié)(從字地址010h開始)被設(shè)置為用戶輸入的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以同樣的方式裝入其他兩個(gè)存儲(chǔ)器代碼塊。
驗(yàn)證程序存儲(chǔ)器代碼
一旦裝入代碼后,有幾種方法來(lái)驗(yàn)證是否正確裝入。- 沒有使用裝入代碼可變長(zhǎng)度命令(10h),而是使用裝入和驗(yàn)證代碼可變長(zhǎng)度命令(50h)。后一命令結(jié)合了代碼裝入操作和驗(yàn)證步驟。
- 或者,也可以調(diào)用驗(yàn)證代碼可變長(zhǎng)度命令(40h)來(lái)單獨(dú)進(jìn)行驗(yàn)證。
- 沒有讓啟動(dòng)加載程序驗(yàn)證裝入的代碼,而是使用卸載代碼可變長(zhǎng)度(20h)命令驗(yàn)證裝入的代碼是否匹配發(fā)送的數(shù)據(jù),JTAG主機(jī)直接驗(yàn)證裝入的數(shù)值。
從程序存儲(chǔ)器卸載代碼
裝入所有代碼后,JTAG演示的最后一步是讀回一個(gè)塊中的所有代碼。向啟動(dòng)加載程序發(fā)送卸載代碼可變長(zhǎng)度(20h)命令來(lái)完成這一讀操作。這一命令的參數(shù)是開始卸載的地址(讀),以及卸載的字節(jié)數(shù)。注意,對(duì)于所有的JTAG啟動(dòng)加載程序命令,必須為每一讀回的字節(jié)發(fā)送一個(gè)字節(jié)。因此,這一命令需要大量的零填充字節(jié),從程序存儲(chǔ)器讀取每一字節(jié)都需要一個(gè)。;;;; ;;;; 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讀取這些代碼字節(jié)后,JTAG演示應(yīng)用程序通過(guò)串口以十六進(jìn)制格式輸出這些代碼字節(jié)。
退出啟動(dòng)加載程序
單字節(jié)命令集0中的命令01h (退出啟動(dòng)加載程序)導(dǎo)致啟動(dòng)加載程序完成操作,并退出,如下所示。- 啟動(dòng)加載程序啟動(dòng)內(nèi)部復(fù)位,把SPE和PSS位清零,復(fù)位微控制器。
- 微控制器退出復(fù)位,開始執(zhí)行程序ROM的8000h。
- 現(xiàn)在SPE已經(jīng)清為零,程序ROM代碼導(dǎo)致執(zhí)行開始于地址0000h的用戶應(yīng)用程序。
;;;; ;;;; 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
操作演示
需要下面的硬件和軟件來(lái)運(yùn)行JTAG啟動(dòng)加載程序演示。硬件
- 兩塊MAXQ2000評(píng)估板(MAXQ2000-K00 REV B);一塊評(píng)估板用作主機(jī)MAXQ2000板,另一塊用作從機(jī)MAXQ2000板。
- MAXQ2000 LCD子卡(MAXQ2000-K01 REV B)
- 兩條2 x 5 JTAG接口電纜(含在MAXQ2000評(píng)估套件中)
- 串口至JTAG接口板(MAXQJTAG-001 REV B)
- DB9直通串行電纜
- 兩個(gè)5V穩(wěn)壓(±5%)直流墻插電源,中心正極,CUI公司。DPR050030-P6或者等效電源。
- 兩個(gè)HC49US 8.00MHz晶振
- 2 x 5 0.100英寸引腳插座
- JTAG演示軟件包
- http://files.dalsemi.com/microcontroller/app_note_software/an4012_sw.zip
- MAXQ的MAX-IDE開發(fā)環(huán)境
- 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評(píng)估套件中的文檔說(shuō)明進(jìn)行下載并安裝。
- 如果還沒有安裝MTK,按照MAXQ2000評(píng)估套件中的文檔說(shuō)明進(jìn)行下載并安裝。
- 連接LCD子卡和從機(jī)MAXQ2000板的J3插座,如前面的圖1所示。LCD子卡應(yīng)固定在MAXQ2000評(píng)估板的上部。
- 在兩塊MAXQ2000評(píng)估板(在Y1)上安裝8.00MHz晶振。
- 在主機(jī)MAXQ2000板的原型區(qū)安裝2 x 5 JTAG插座,引腳連接至主機(jī)MAXQ2000引腳,如表1所列。
- 配置串口至JTAG板以及兩塊MAXQ2000評(píng)估板上的跳線和DIP開關(guān),如表2所列。
- 使用DB9串行電纜連接PC的COM1口和串口至JTAG板的J1。
- 將第一個(gè)5V電源連接至串口至JTAG板的J2。
- 將第二個(gè)5V電源連接至從機(jī)MAXQ2000評(píng)估板的J1。
- 使用第一條JTAG電纜,連接串口至JTAG板的P2和主機(jī)MAXQ2000板的J4。紅色線應(yīng)連接兩個(gè)JTAG插座的引腳1。
- 使用第二條JTAG電纜,連接主機(jī)MAXQ2000板原型區(qū)的JTAG插座和從機(jī)MAXQ2000板的J4。紅色線應(yīng)連接兩個(gè)JTAG插座的引腳1。
- 下載JTAG演示軟件包,把它解壓縮到工作路徑中。
- 啟動(dòng)MAX-IDE。
- 打開兩路5V電源。
- 從菜單中選擇Project
Open Project ,選擇maxqjtag.prj工程文件,打開它。
- 從菜單中選擇Debug
Make。應(yīng)出現(xiàn)"Build Successful"消息。
- 從菜單中選擇Debug
Run。應(yīng)出現(xiàn)一連串的"Loading"消息,隨后是"Done"。
- 從菜單中選擇Debug
Stop。
- 關(guān)閉MAX-IDE。
- 關(guān)掉電源。
- 在斷電情況下,從串口至JTAG板斷開DB9串行電纜。
- DB9電纜連接至主機(jī)MAXQ2000板的J5。
- 啟動(dòng)MTK。在起始對(duì)話框中選擇"Dumb Terminal"。
- 從菜單中選擇Options
Configure Serial Port。在對(duì)話框中,設(shè)置Port為COM1,Speed為9600波特率。
- 從菜單中選擇Target
Open COM1 at 9600 baud。
- 打開電源。

圖5. 演示應(yīng)用程序,串口提示符
現(xiàn)在輸入一個(gè)4位十進(jìn)制數(shù);不需要隨后按下回車鍵。演示應(yīng)用程序會(huì)完成剩下的操作(主機(jī)擦除、裝入代碼和卸載代碼),并輸出結(jié)果,以及從程序存儲(chǔ)器中卸載的十六進(jìn)制字節(jié)值,如圖6所示。

圖6. 演示應(yīng)用程序,串口輸出
電子發(fā)燒友App






















































評(píng)論