// --------------------------------------------------------------------------- // @file jtag.c // @brief JTAG basic commands // // @author Laurent Saint-Marcel (lstmarcel@yahoo.fr) // @date 2009/09/25 // --------------------------------------------------------------------------- // Thanks to http://www.fpga4fun.com/JTAG4.html for the JTAG protocol description! #include <avr/io.h> #include <util/delay.h> #include "util.h" #include "jtag.h" #define TMS_0 0 #define TMS_1 1 #define TDI_0 0 #define TDI_1 1 // pin configuration #define JTAG_DDR DDRB #define TMS_PORT PORTB #define TMS_PIN 1 #define TDI_PORT PORTB #define TDI_PIN 3 #define TDO_PORT PINB #define TDO_PIN 2 #define TCLK_PORT PORTB #define TCLK_PIN 0 // Additional pin used to force the reset of the target AVR. It is connected // to the reset pin of the target #define JTAG_RESET_DDR DDRA #define JTAG_RESET_PORT PORTA #define JTAG_RESET_PIN 3 // --------------------------------------------------------------------------- // Initialize the IO port of the atmel // --------------------------------------------------------------------------- void jtagInit() { // reset pin output sbi(JTAG_RESET_DDR, JTAG_RESET_PIN); sbi(JTAG_RESET_PORT, JTAG_RESET_PIN); // outputs sbi(JTAG_DDR, TMS_PIN); sbi(JTAG_DDR, TDI_PIN); sbi(JTAG_DDR, TCLK_PIN); // inputs cbi(JTAG_DDR, TDO_PIN); } // --------------------------------------------------------------------------- // Set the Jtag Reset pin state // --------------------------------------------------------------------------- void jtagReset(unsigned char reset) { if (reset) { cbi(JTAG_RESET_PORT, JTAG_RESET_PIN); } else { sbi(JTAG_RESET_PORT, JTAG_RESET_PIN); } } // --------------------------------------------------------------------------- // send one byte to the jtag with one clock pulse, return the TDO bit value // --------------------------------------------------------------------------- unsigned char jtagClockPulse(unsigned char tms, unsigned char tdi) { if (tms != 0) sbi(TMS_PORT, TMS_PIN); else cbi(TMS_PORT, TMS_PIN); if (tdi != 0) sbi(TDI_PORT, TDI_PIN); else cbi(TDI_PORT, TDI_PIN); // clock raising edge sbi(TCLK_PORT, TCLK_PIN); // clock falling edge cbi(TCLK_PORT, TCLK_PIN); return bit_is_set(TDO_PORT, TDO_PIN); } // --------------------------------------------------------------------------- // set the JTAG in the Run-Test/Idle state from any state // --------------------------------------------------------------------------- void jtagTestLogicReset() { unsigned char i; // first sync everybody to the test-logic-reset state for(i=0; i<5; i++) { jtagClockPulse(TMS_1, TDI_0); } } // --------------------------------------------------------------------------- // set the JTAG in the Shift IR state // --------------------------------------------------------------------------- void jtagShiftIR() { jtagClockPulse(TMS_0, TDI_0); jtagClockPulse(TMS_1, TDI_0); jtagClockPulse(TMS_1, TDI_0); jtagClockPulse(TMS_0, TDI_0); jtagClockPulse(TMS_0, TDI_0); } // --------------------------------------------------------------------------- // Prerequisit: must be in the ShiftIR state // write 4 bits in the IR register of the JTAG and go in the update IR state // --------------------------------------------------------------------------- void jtagWriteIR(unsigned char data) { unsigned char bit; for(bit =0; bit<4; ++bit) { jtagClockPulse(bit == 3/*tms*/, // go in the update DR state at last bit (data & (1 << bit))/*tdi*/); } } // --------------------------------------------------------------------------- // set the JTAG in the Shift DR state // --------------------------------------------------------------------------- void jtagShiftDR() { jtagClockPulse(TMS_0, TDI_0); jtagClockPulse(TMS_1, TDI_0); jtagClockPulse(TMS_0, TDI_0); jtagClockPulse(TMS_0, TDI_0); } // --------------------------------------------------------------------------- // Prerequisit: must be in the ShiftIR state // write 'length" bits of 'data' in the DR register of the JTAG // Go in the update DR state at last bit if exitAtLast != 0 or remain in the // Shift DR state // --------------------------------------------------------------------------- unsigned char jtagWriteDR(unsigned char data, unsigned char length, unsigned char exitAtLast) { //_delay_us(10); unsigned char result = 0; unsigned char bit; for(bit =0; bit < length; ++bit) { unsigned char tms = TMS_0; if ((exitAtLast != 0) && (bit == (length-1))) { tms = TMS_1; // to exit the Shift-DR state after last bit is set } if ((jtagClockPulse(tms, (data & (1 << bit)) ) != 0)) { result |= (1 << bit); } } return result; } // --------------------------------------------------------------------------- // set the JTAG in the RunTestIdle state after being in IR or DR state // --------------------------------------------------------------------------- void jtagRunTestIdle() { jtagClockPulse(TMS_1, TDI_0); jtagClockPulse(TMS_0, TDI_0); }