view src/jtag.c @ 7:61f27549de57

Support TRST.
author Thinker K.F. Li <thinker@branda.to>
date Sun, 22 Feb 2009 14:20:57 +0800
parents eb14cac68cbb
children cc106f278d7d
line wrap: on
line source

#include <stdio.h>
#include <util/delay.h>
#include "jtag.h"
#include "avriotools.h"

/* It is supposed to work at 1Mbps */
#define CLK_DELAY()

void jtag_init(void) {
    pin_mode(&JTAG_PORT, JTAG_TCK, PM_OUTPUT);
    pin_mode(&JTAG_PORT, JTAG_TMS, PM_OUTPUT);
    pin_mode(&JTAG_PORT, JTAG_TDI, PM_OUTPUT);
    pin_mode(&JTAG_PORT, JTAG_TDO, PM_INPUT);
    pin_lo(JTAG_PORT, JTAG_TCK);
    pin_lo(JTAG_PORT, JTAG_TMS);
    pin_lo(JTAG_PORT, JTAG_TDI);
}

#define TCK_LO() pin_lo(JTAG_PORT, JTAG_TCK)
#define TCK_HI() pin_hi(JTAG_PORT, JTAG_TCK)
#define SEND_BIT(pin, bit)			\
    do {					\
	if(bit)					\
	    pin_hi(JTAG_PORT, pin);		\
	else					\
	    pin_lo(JTAG_PORT, pin);		\
	CLK_DELAY();				\
	TCK_HI();				\
	CLK_DELAY();				\
    } while(0)
#define GET_TDO() (JTAG_PIN & _BV(JTAG_TDO))

void jtag_trst(void) {
    SEND_BIT(JTAG_TRST, 1);
    TCK_LO();
    pin_lo(JTAG_PORT, JTAG_TRST);
}

/*!
 * Before shifting registers, TAP controller must move to last state before
 * shift state.  The state machine transite to shift state when shifting
 * starts.
 */
void jtag_tms(char *buf, int nbits) {
    int i;
    int nbytes, byte;
    int byteoff, bitoff;
    int bit;
    
    nbytes = nbits / 8;
    for(i = 0; i < nbytes; i++) {
	byte = buf[i];
	
	bit = byte & 0x01;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x02;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x04;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x08;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x10;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x20;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x40;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
	
	bit = byte & 0x80;
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
    }
    
    byte = buf[i];
    nbits %= 8;
    for(i = 0; i < nbits; i++) {
	bit = byte & (1 << i);
	SEND_BIT(JTAG_TMS, bit);
	TCK_LO();
    }
}

void jtag_shift(char *buf, int nbits) {
    int i;
    int nbytes, byte;
    int byteoff, bitoff;
    int bit;
    
    /* Transite to shift state.
     * \sa jtag_tms()
     */
    pin_lo(JTAG_PORT, JTAG_TMS);

    nbytes = nbits / 8;
    for(i = 0; i < nbytes; i++) {
	byte = buf[i];
	
	bit = byte & 0x01;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x02;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x04;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x08;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x10;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x20;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x40;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
	
	bit = byte & 0x80;
	SEND_BIT(JTAG_TDI, bit);
	TCK_LO();
    }
    
    nbits %= 8;
    if(nbits) {
	byte = buf[i];
	for(i = 0; i < nbits; i++) {
	    bit = byte & (1 << i);
	    SEND_BIT(JTAG_TDI, bit);
	    TCK_LO();
	}
    }
}

void jtag_shift_inout(char *ibuf, char *obuf, int nbits) {
    int i, j;
    int nbytes, byte, obyte;
    int tdo;
    int byteoff, bitoff;
    int bit;
    
    /* Transite to shift state.
     * \sa jtag_tms()
     */
    pin_lo(JTAG_PORT, JTAG_TMS);

    nbytes = nbits / 8;
    for(i = 0; i < nbytes; i++) {
	byte = ibuf[i];
	obyte = 0;
	
	bit = byte & 0x01;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x01;
	else
	    obyte &= ~0x01;
	TCK_LO();
	
	bit = byte & 0x02;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x02;
	else
	    obyte &= ~0x02;
	TCK_LO();
	
	bit = byte & 0x04;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x04;
	else
	    obyte &= ~0x04;
	TCK_LO();
	
	bit = byte & 0x08;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x08;
	else
	    obyte &= ~0x08;
	TCK_LO();
	
	bit = byte & 0x10;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x10;
	else
	    obyte &= ~0x10;
	TCK_LO();
	
	bit = byte & 0x20;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x20;
	else
	    obyte &= ~0x20;
	TCK_LO();
	
	bit = byte & 0x40;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x40;
	else
	    obyte &= ~0x40;
	TCK_LO();
	
	bit = byte & 0x80;
	SEND_BIT(JTAG_TDI, bit);
	tdo = GET_TDO();
	if(tdo)
	    obyte |= 0x80;
	else
	    obyte &= ~0x80;
	TCK_LO();

	obuf[i] = obyte;
    }
    
    nbits %= 8;
    if(nbits) {
	byte = ibuf[i];
	obyte = 0;
	for(j = 0; j < nbits; j++) {
	    bit = byte & (1 << j);
	    SEND_BIT(JTAG_TDI, bit);
	    tdo = GET_TDO();
	    if(tdo)
		obyte |= 1 << j;
	    else
		obyte &= ~(1 << j);
	    TCK_LO();
	}
	obuf[i] = obyte;
    }
}