# HG changeset patch # User Thinker K.F. Li # Date 1235228810 -28800 # Node ID abf221bf3ce4c6df4d80c66e919031d96460c383 # Parent f7c60e5258015970f413cae397b844c3a0362472 AVR JTAG server. diff -r f7c60e525801 -r abf221bf3ce4 include/cmd_proto.h --- 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; diff -r f7c60e525801 -r abf221bf3ce4 include/jtag.h --- /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 + +#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_ */ diff -r f7c60e525801 -r abf221bf3ce4 src/Makefile --- /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 diff -r f7c60e525801 -r abf221bf3ce4 src/avr_jtag.c --- /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 +#include +#include +#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); + } + } +} diff -r f7c60e525801 -r abf221bf3ce4 src/jtag.c --- /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 +#include +#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); + } +}