📄 jtag_avr_spy.asm
字号:
;###############################################################################;# jtag_spy_avr.asm version 1.0;# 2002 Copyright (C) A.M. ten Doesschate <a.doesschate@hccnet.nl>;#;# This program is free software; you can redistribute it and/or modify;# it under the terms of the GNU General Public License as published by;# the Free Software Foundation; either version 2 of the License, or;# (at your option) any later version.;#;# This program is distributed in the hope that it will be useful,;# but WITHOUT ANY WARRANTY; without even the implied warranty of;# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;# GNU General Public License for more details.;#;# You should have received a copy of the GNU General Public License;# along with this program; if not, write to the Free Software;# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA;#;# jtag_avr_spy can be used to capture the AVR JTAG ICE and dump result;# on RS232 to the GNU/Linux host this application is optimized as fast as;# I could to gain speed. This means there is used as little as memory;# referencing.;#;# It uses the AVR assembler supplied in AVR Studio tools but doesn't rely on;# predefined macros - so, this tool can be used with the GNU tool-chain, too.;#;############################################################################### .device atmega16 .include "io_atmega16.inc" .include "constant.inc" .def zero_reg = r0 .def one_reg = r1 .def rx_in_lo = r2 .def rx_in_hi = r3 .def rx_out_lo = r4 .def rx_out_hi = r5 .def rx_end_lo = r6 .def rx_end_hi = r7 .def tx_in_lo = r8 .def tx_in_hi = r9 .def tx_out_lo = r10 .def tx_out_hi = r11 .def tx_end_lo = r12 .def tx_end_hi = r13 .def int0_in_lo = r14 .def int0_in_hi = r15 .def int0_out_lo = r16 .def int0_out_hi = r17 .def tck_cnt = r18 .def level = r19 .def jtag_byte_nr = r20 .def jtag_bit_nr = r21 .def state = r22 .def sh_tdx_bit = r23 .def jptr_inl = r26 .def jptr_inh = r27 .def jptr_outl = r28 .def jptr_outh = r29 .equ jtag_port = pind .equ stack = 160;*---------------------------------------------------------------------------- .dseg .org stackrx_cnt : .byte 1 ; receiver semaphore counttx_cnt : .byte 1 ; transmitter semphore countrx_buf : .byte MAX_BUF tx_buf : .byte MAX_BUFtx_end : .byte 2rx_end : .byte 2rx_in : .byte 2 ; ptr to receiver buffer of interruptrx_out : .byte 2 ; ptr to receiver buffer of main looptx_in : .byte 2tx_out : .byte 2jtag_in : .byte MAX_BUF ; TDI bufferjtag_out : .byte MAX_BUF ; TDO bufferint0_cnt : .byte 1 ; JTAG semaphore count of interrupt INT0int0_in : .byte 2 ; ptr to JTAG buffer of interruptint0_out : .byte 2 ; ptr to JTAG buffer of main loopint0_buf : .byte MAX_BUF;*----------------------------------------------------------------------------;* vector region;*---------------------------------------------------------------------------- .cseg jmp main jmp int0_isr jmp int1_isr jmp toc2_isr jmp toc2_ovf_isr jmp tic1_isr jmp toc1a_isr jmp toc1b_isr jmp toc1_ovf_isr jmp toc0_ovf_isr jmp spi_isr jmp rxd_isr jmp udre_isr jmp txc_isr jmp adc_isr jmp ee_rdy_isr jmp ana_comp_isr jmp i2c_isr jmp int2_isr jmp toc0_isr jmp spm_rdy_isr;*----------------------------------------------------------------------------;* rising edge if TCK generates interrupt. Read all JTAG info (TMS, TDI, TDO);* in : -;* out : -;* used : r23, r24, r25, r30, r31;*----------------------------------------------------------------------------int0_isr : push r23 push r24 push r25 push r30 push r31 in r23,sreg ; save processor state lds r24,int0_cnt ; check for space in queue cpi r24,MAX_BUF brcc int0_1 inc r24 ; then update queue sts int0_cnt,r24 ; and total to manage mov r30,int0_in_lo mov r31,int0_in_hi in r24,jtag_port st z+,r24 ; get jtag port signals ldi r24,low(int0_buf) ; check end of queue ldi r25,high(int0_buf) adiw r25:r24,MAX_BUF cp r30,r24 ; reached cpc r31,r25 brcs int0_2 ; if so then go to start ldi r30,low(int0_buf) ; of buffer ldi r31,high(int0_buf)int0_2 : mov int0_in_lo,r30 mov int0_in_hi,r31int0_1 : out sreg,r23 pop r31 pop r30 pop r25 pop r24 pop r23 reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------int1_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc2_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc2_ovf_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------tic1_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc1a_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc1b_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc1_ovf_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc0_ovf_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------spi_isr : reti;*----------------------------------------------------------------------------;* receiver interrupt. Maybe neccesary;* in : -;* out : -;* used : r23, r24, r25, r30, r31;*----------------------------------------------------------------------------rxd_isr : push r23 push r24 push r25 push r30 push r31 in r23,sreg ; save status register in r24,usr ; read status in r25,udr ; and read character andi r24,(1<<FE) + (1<<OR) ; check errors brne rxd1 ; if so throw away lds r24,rx_cnt ; check character count inc r24 ; increment count sts rx_cnt,r24 mov r30,rx_in_lo mov r31,rx_in_hi ; put character into buffer st z+,r25 ; point to next space cp r30,rx_end_lo ; reached cpc r31,rx_end_hi brcs rxd2 ; if so then go to start ldi r30,low(rx_buf) ; of buffer ldi r31,high(rx_buf)rxd2 : mov rx_in_lo,r30 mov rx_in_hi,r31rxd1 : out sreg,r23 ; restore status register pop r31 pop r30 pop r25 pop r24 pop r23 reti;*----------------------------------------------------------------------------;* transmitter interrupt.;* in : -;* out : -;* used : r23, r24, r30, r31;*----------------------------------------------------------------------------udre_isr : push r23 push r24 push r30 push r31 in r23,sreg ; save status register lds r24,tx_cnt ; check transmit count dec r24 brpl txd1 ; all done ? cbi ucr,UDRIE ; check if interrupt enabled rjmp txd2 ; and disable interrupttxd1 : sts tx_cnt,r24 mov r30,tx_out_lo ; get next character mov r31,tx_out_hi ; in output buffer ld r24,z+ ; and output it into out udr,r24 ; RS232 line cp r30,tx_end_lo ; end of buffer ? cpc r31,tx_end_hi brcs txd3 ldi r30,low(tx_buf) ; then start of buffer ldi r31,high(tx_buf)txd3 : mov tx_out_lo,r30 ; and update ptr mov tx_out_hi,r31txd2 : out sreg,r23 ; restore status register pop r31 pop r30 pop r24 pop r23 reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------txc_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------adc_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------ee_rdy_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------ana_comp_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------i2c_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------int2_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------toc0_isr : reti;*----------------------------------------------------------------------------;*----------------------------------------------------------------------------spm_rdy_isr : reti;*----------------------------------------------------------------------------;* maybe neccesary;* in : -;* out : r24, character;* used : r25, r30, r31;*----------------------------------------------------------------------------getch : push r25 push r30 push r31getch1 : lds r25,rx_cnt ; check if semaphore > 0 dec r25 brmi getch1 cli ; if so disable global interrupt lds r25,rx_cnt ; while it can change the count dec r25 ; decrement count sts rx_cnt,r25 mov r30,rx_out_lo mov r31,rx_out_hi ; and get character ld r24,z+ sei ; enable interrupt cp r30,rx_end_lo cpc r31,rx_end_hi brcs getch2 ; if so then point to start ldi r30,low(rx_buf) ; of buffer ldi r31,high(rx_buf)getch2 : mov rx_out_lo,r30 mov rx_out_hi,r31 pop r31 pop r30 pop r25 ret;*----------------------------------------------------------------------------;* in : r24, character;* out : -;* used : r24, r25, r30, r31;*----------------------------------------------------------------------------outch : push r24 push r25 push r30 push r31outch1 : lds r25,tx_cnt ; check if room in queue inc r25 cpi r25,MAX_BUF brcc outch1 cli ; ok then check if lds r25,tx_cnt ; transmitter is realy tst r25 ; free brne outch2 sbis usr,UDRE rjmp outch2 ; then write immediately out udr,r24 ; character sei rjmp outch3 ; else;outch2 : sbis ucr,UDRIE ; check if interrupt enabled sbi ucr,UDRIE ; if so enable SCI interrupt inc r25 ; increment total character sts tx_cnt,r25 ; count to transmit mov r30,tx_in_lo ; and put into buffer mov r31,tx_in_hi st z+,r24 ; AVR is very fast so sei ; enable interrupt again cp r30,tx_end_lo cpc r31,tx_end_hi brcs outch4 ; if so then point to begin ldi r30,low(tx_buf) ; of buffer ldi r31,high(tx_buf)outch4 : mov tx_in_lo,r30 mov tx_in_hi,r31outch3 : pop r31 pop r30 pop r25 pop r24 ret;*----------------------------------------------------------------------------;* dump JTAG byte to RS232;* in : r24 : byte;* out : -;* used : r25;*----------------------------------------------------------------------------out_byte : push r25 mov r25,r24 ; save low nibble swap r24 andi r25,0xf andi r24,0xf ; check >= 10 cpi r24,10 brcc out_byte1 subi r24,-0x30 ; then it is '0' to '9' rjmp out_byte2 ; elseout_byte1 : subi r24,-0x37 ; 'A' to 'F'out_byte2 : rcall outch mov r24,r25 ; now low nibble cpi r24,10 brcc out_byte3 subi r24,-0x30 ; then it is '0' to '9' rjmp out_byte4 ; elseout_byte3 : subi r24,-0x37 ; 'A' to 'F'out_byte4 : rcall outch pop r25 ret;*----------------------------------------------------------------------------;* Must do this way in order not to miss any rising edge of TCK;* in : -;* out :level;* used : r25, r30, r31 ;*----------------------------------------------------------------------------chk_tck : push r25 push r30 push r31chk_tck1 : lds r25,int0_cnt ; check if semaphore > 0 dec r25 brmi chk_tck1 cli ; if so disable global interrupt lds r25,int0_cnt ; while it can change the count dec r25 ; decrement count sts int0_cnt,r25 mov r30,int0_out_lo mov r31,int0_out_hi ; and get character ld level,z+ sei ; enable interrupt ldi r24,low(int0_buf) ; check end of queue ldi r25,high(int0_buf) adiw r25:r24,MAX_BUF cp r30,r24 cpc r31,r25
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -