view src/jtag.c @ 10:cc106f278d7d

Get identify of components
author Thinker K.F. Li <thinker@branda.to>
date Tue, 24 Feb 2009 13:32:04 +0800
parents 61f27549de57
children 1ea479d26fce
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() _delay_us(1)

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_mode(&JTAG_PORT, JTAG_TRST, PM_OUTPUT);
    pin_lo(JTAG_PORT, JTAG_TCK);
    pin_lo(JTAG_PORT, JTAG_TMS);
    pin_lo(JTAG_PORT, JTAG_TDI);
    pin_hi(JTAG_PORT, JTAG_TRST);
}

#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();				\
	TCK_LO();				\
    } while(0)
#define GET_TDO() (JTAG_PIN & _BV(JTAG_TDO))
#define SEND_GET_BIT(pin, bit, out)		\
    do {					\
	if(bit)					\
	    pin_hi(JTAG_PORT, pin);		\
	else					\
	    pin_lo(JTAG_PORT, pin);		\
	CLK_DELAY();				\
	TCK_HI();				\
	CLK_DELAY();				\
	out = GET_TDO();			\
	TCK_LO();				\
    } while(0)

void jtag_trst(void) {
    pin_lo(JTAG_PORT, JTAG_TRST);
    SEND_BIT(JTAG_TMS, 1);
    SEND_BIT(JTAG_TMS, 1);
    SEND_BIT(JTAG_TMS, 1);
    SEND_BIT(JTAG_TMS, 1);
    SEND_BIT(JTAG_TMS, 1);
    pin_hi(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(unsigned char *buf, int nbits) {
    int i;
    int nbytes, byte;
    int byteoff, bitoff;
    int bit;
    
    pin_hi(JTAG_PORT, JTAG_TDI);

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

void jtag_shift(unsigned char *buf, int nbits) {
    int i;
    int nbits_1;
    int nbytes, byte;
    int byteoff, bitoff;
    int bit, remain;

    if(nbits == 0)
	return;
    
    /* Transite to shift state.
     * \sa jtag_tms()
     */
    pin_lo(JTAG_PORT, JTAG_TMS);

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

    byte = buf[nbits / 8];
    bit = byte & (1 << (nbits_1 % 8));
    
    pin_hi(JTAG_PORT, JTAG_TMS);
    SEND_BIT(JTAG_TDI, bit);
}

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

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

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

    byte = ibuf[nbits / 8];
    bit = byte & (1 << (nbits_1 % 8));

    pin_hi(JTAG_PORT, JTAG_TMS);
    SEND_GET_BIT(JTAG_TDI, bit, tdo);
    if(tdo)
	obuf[nbits / 8] |= 1 << j;
    else
	obuf[nbits / 8] &= ~(1 << j);
}