changeset 2:abf221bf3ce4

AVR JTAG server.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 21 Feb 2009 23:06:50 +0800
parents f7c60e525801
children e410832c3280
files include/cmd_proto.h include/jtag.h src/Makefile src/avr_jtag.c src/jtag.c
diffstat 5 files changed, 244 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/include/cmd_proto.h	Sat Feb 21 20:20:06 2009 +0800
+++ b/include/cmd_proto.h	Sat Feb 21 23:06:50 2009 +0800
@@ -6,13 +6,13 @@
 typedef enum {
     CPCMD_DUMMY,
     CPCMD_PING,
+    CPCMD_SHIFT_TDI,
+    CPCMD_SHIFT_TMS,
+    CPCMD_SHIFT_TDI_TDO,
     CPCMD_PONG,
     CPCMD_DATA,
     CPCMD_ACK,
     CPCMD_NAK,
-    CPCMD_SHIFT_TDI,
-    CPCMD_SHIFT_TMS,
-    CPCMD_SHIFT_TDI_TDO,
     CPCMD_MAX
 } cp_ccode_t;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/jtag.h	Sat Feb 21 23:06:50 2009 +0800
@@ -0,0 +1,18 @@
+#ifndef __JTAG_H_
+#define __JTAG_H_
+
+#include <avr/io.h>
+
+#define JTAG_PORT PORTB
+#define JTAG_PIN PINB
+#define JTAG_TCK PINB0
+#define JTAG_TMS PINB1
+#define JTAG_TDI PINB2
+#define JTAG_TDO PINB3
+
+extern void jtag_init(void);
+extern void jtag_tms(char *buf, int nbits);
+extern void jtag_shift(char *buf, int nbits);
+extern void jtag_shift_inout(char *ibuf, char *obuf, int nbits);
+
+#endif /* __JTAG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Makefile	Sat Feb 21 23:06:50 2009 +0800
@@ -0,0 +1,33 @@
+CFLAGS =	-DF_CPU=16000000UL -mmcu=atmega168 -I../include -O2
+AVR_JTAG_OBJS =	\
+	avr_jtag.o	\
+	avriotools.o	\
+	cmd_proto.o	\
+	jtag.o
+CC= avr-gcc
+OBJCOPY= avr-objcopy
+PORT?= /dev/cuaU0
+
+all: avr_jtag.hex
+
+avr_jtag.hex: avr_jtag
+	$(OBJCOPY) -O ihex -R .eeprom $(.ALLSRC) $@
+
+avr_jtag: $(AVR_JTAG_OBJS)
+	$(CC) -o $@ $(.ALLSRC)
+
+$(AVR_JTAG_OBJS): ${@:C/\.o/.c/}
+	$(CC) $(CFLAGS) -c $(.ALLSRC)
+
+install:
+	avrdude -V -F -c stk500v1 -p m168 -b 19200 -P $(PORT) \
+		-U flash:w:avr_jtag.hex
+
+
+clean:
+	@for f in $(AVR_JTAG_OBJS) avr_jtag avr_jtag.hex *~; do \
+		if [ -e $$f ]; then \
+			echo "delete $$f"; \
+			rm -f $$f; \
+		fi; \
+	done
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/avr_jtag.c	Sat Feb 21 23:06:50 2009 +0800
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "avriotools.h"
+#include "cmd_proto.h"
+#include "jtag.h"
+
+#define BAUD_RATE 420000
+
+static char client_buf[255 + CP_CMD_OVERHEAD];
+
+static
+void ack(int seq) {
+    int i;
+    int sz;
+    
+    sz = cmd_proto_cmd_fill(client_buf, seq, CPCMD_ACK, 0);
+    
+    for(i = 0; i < sz; i++)
+	uart_putc(client_buf[i]);
+}
+
+static
+void nak(int seq, const char *msg) {
+    int i;
+    int sz;
+    
+    memcpy(client_buf + CP_CMD_HEAD_SZ, msg, strlen(msg));
+    sz = cmd_proto_cmd_fill(client_buf, seq, CPCMD_NAK, 7);
+    
+    for(i = 0; i < sz; i++)
+	uart_putc(client_buf[i]);
+}
+
+static
+void send_client(const char *buf, int bsz) {
+    int i;
+    
+    for(i = 0; i < bsz; i++)
+	uart_putc(buf[i]);
+}
+
+#define GET_DATA_BITS(data) ((data)[0] | ((data)[1] << 8))
+
+int main(int argc, char * const argv[]) {
+    cp_cmd_t *cmd;
+    cmd_proto_t *cp;
+    int c, nbits;
+    int bsz;
+    char buf[16];
+    
+    jtag_init();
+    uart_init(BAUD_RATE);
+
+    cp = cmd_proto_new();
+    
+    while(1) {
+	uart_getc(c);
+	cmd = cmd_proto_rcv(cp, c);
+
+	if(cmd == &BAD_CMD) {
+	    nak(cmd->seq, "BAD CMD");
+	    continue;
+	}
+	
+	if(cmd == &CSUM_ERR_CMD) {
+	    nak(cmd->seq, "CSUM ERR");
+	    continue;
+	}
+	
+	switch(cmd->code) {
+	case CPCMD_PING:
+	    memcpy(client_buf + CP_CMD_HEAD_SZ, cmd->data, cmd->data_sz);
+	    bsz = cmd_proto_cmd_fill(client_buf, cmd->seq,
+				     CPCMD_PONG, cmd->data_sz);
+	    send_client(client_buf, bsz);
+	    break;
+	    
+	case CPCMD_SHIFT_TDI:
+	    nbits = GET_DATA_BITS(cmd->data);
+	    jtag_shift(cmd->data + 2, nbits);
+	    ack(cmd->seq);
+	    break;
+	    
+	case CPCMD_SHIFT_TMS:
+	    nbits = GET_DATA_BITS(cmd->data);
+	    jtag_tms(cmd->data + 2, nbits);
+	    ack(cmd->seq);
+	    break;
+	    
+	case CPCMD_SHIFT_TDI_TDO:
+	    nbits = GET_DATA_BITS(cmd->data);
+	    jtag_shift_inout(cmd->data + 2,
+			     client_buf + CP_CMD_HEAD_SZ + 2,
+			     nbits);
+	    
+	    client_buf[CP_CMD_HEAD_SZ] = nbits & 0xff;
+	    client_buf[CP_CMD_HEAD_SZ + 1] = nbits >> 8;
+	    
+	    bsz = cmd_proto_cmd_fill(client_buf, cmd->seq,
+				     CPCMD_DATA, (nbits + 23) / 8);
+	    send_client(client_buf, bsz);
+	    break;
+	    
+	default:
+	    sprintf(buf, "CODE 0x%02x", cmd->code);
+	    nak(cmd->seq, buf);
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jtag.c	Sat Feb 21 23:06:50 2009 +0800
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <util/delay.h>
+#include "jtag.h"
+#include "avriotools.h"
+
+/* It is supposed to work at 1Mbps */
+#define CLK_DELAY() do { _delay_ms(0.0004); } while(0)
+
+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, JTAG_TDI);	\
+	else					\
+	    pin_lo(JTAG_PORT, JTAG_TDI);	\
+	CLK_DELAY();				\
+	TCK_HI();				\
+	CLK_DELAY();				\
+    } while(0)
+#define GET_TDO() (JTAG_PIN & _BV(JTAG_TDO))
+
+void jtag_tms(char *buf, int nbits) {
+    int i;
+    int byteoff, bitoff;
+    int bit;
+    
+    for(i = 0; i < nbits; i++) {
+	byteoff = i / 8;
+	bitoff = i % 8;
+	bit = buf[byteoff] & (1 << bitoff);
+	SEND_BIT(JTAG_TMS, bit);
+	TCK_LO();
+    }
+}
+
+void jtag_shift(char *buf, int nbits) {
+    int i;
+    int byteoff, bitoff;
+    int bit;
+    
+    for(i = 0; i < nbits; i++) {
+	byteoff = i / 8;
+	bitoff = i % 8;
+	bit = buf[byteoff] & (1 << bitoff);
+	SEND_BIT(JTAG_TDI, bit);
+	TCK_LO();
+    }
+}
+
+void jtag_shift_inout(char *ibuf, char *obuf, int nbits) {
+    int i;
+    int byteoff, bitoff;
+    int bit, tdo, bitmask;
+    
+    for(i = 0; i < nbits; i++) {
+	byteoff = i / 8;
+	bitoff = i % 8;
+	bitmask = 1 << bitoff;
+	
+	bit = ibuf[byteoff] & bitmask;
+	SEND_BIT(JTAG_TDI, bit);
+	tdo = GET_TDO();
+	TCK_LO();
+	if(tdo)
+	    obuf[byteoff] |= bitmask;
+	else
+	    obuf[byteoff] &= ~(bitmask);
+    }
+}