jtagmkii.c

来自「这是一个非常有价值的参考代码」· C语言 代码 · 共 1,822 行 · 第 1/4 页

C
1,822
字号
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2005 Joerg Wunsch <j@uriah.heep.sax.de> * * Derived from stk500 code which is: * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * Copyright (C) 2005 Erik Walthinsen * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* $Id: jtagmkII.c,v 1.9 2005/09/16 15:52:28 joerg_wunsch Exp $ *//* * avrdude interface for Atmel JTAG ICE mkII programmer */#include "ac_cfg.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/time.h>#include <time.h>#include "avr.h"#include "crc16.h"#include "pgm.h"#include "jtagmkII_private.h"#include "serial.h"extern int    verbose;extern char * progname;extern int do_cycles;/* * XXX There should really be a programmer-specific private data * pointer in struct PROGRAMMER. */static unsigned short command_sequence; /* Next cmd seqno to issue. *//* * See jtagmkII_read_byte() for an explanation of the flash and * EEPROM page caches. */static unsigned char *flash_pagecache;static unsigned long flash_pageaddr;static unsigned int flash_pagesize;static unsigned char *eeprom_pagecache;static unsigned long eeprom_pageaddr;static unsigned int eeprom_pagesize;static int prog_enabled;	/* Cached value of PROGRAMMING status. */static unsigned char serno[6];	/* JTAG ICE serial number. *//* * The OCDEN fuse is bit 7 of the high fuse (hfuse).  In order to * perform memory operations on MTYPE_SPM and MTYPE_EEPROM, OCDEN * needs to be programmed. * * OCDEN should probably rather be defined via the configuration, but * if this ever changes to a different fuse byte for one MCU, quite * some code here needs to be generalized anyway. */#define OCDEN (1 << 7)/* The length of the device descriptor is firmware-dependent. */static size_t device_descriptor_length;static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,			      unsigned long addr, unsigned char * value);static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,			       unsigned long addr, unsigned char data);static int jtagmkII_set_sck_period(PROGRAMMER * pgm, double v);static int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,			    unsigned char * value);static int jtagmkII_setparm(PROGRAMMER * pgm, unsigned char parm,			    unsigned char * value);static void jtagmkII_print_parms1(PROGRAMMER * pgm, char * p);static unsigned longb4_to_u32(unsigned char *b){  unsigned long l;  l = b[0];  l += (unsigned)b[1] << 8;  l += (unsigned)b[2] << 16;  l += (unsigned)b[3] << 24;  return l;}static voidu32_to_b4(unsigned char *b, unsigned long l){  b[0] = l & 0xff;  b[1] = (l >> 8) & 0xff;  b[2] = (l >> 16) & 0xff;  b[3] = (l >> 24) & 0xff;}static unsigned shortb2_to_u16(unsigned char *b){  unsigned short l;  l = b[0];  l += (unsigned)b[1] << 8;  return l;}static voidu16_to_b2(unsigned char *b, unsigned short l){  b[0] = l & 0xff;  b[1] = (l >> 8) & 0xff;}static void jtagmkII_print_memory(unsigned char *b, size_t s){  int i;  if (s < 2)    return;  for (i = 0; i < s - 1; i++) {    fprintf(stderr, "0x%02x ", b[i + 1]);    if (i % 16 == 15)      putc('\n', stderr);    else      putc(' ', stderr);  }  if (i % 16 != 0)    putc('\n', stderr);}static void jtagmkII_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len){  int i;  if (verbose >= 4) {    fprintf(stderr, "Raw message:\n");    for (i = 0; i < len; i++) {      fprintf(stderr, "0x%02x", data[i]);      if (i % 16 == 15)	putc('\n', stderr);      else	putchar(' ');    }    if (i % 16 != 0)      putc('\n', stderr);  }  switch (data[0]) {  case RSP_OK:    fprintf(stderr, "OK\n");    break;  case RSP_FAILED:    fprintf(stderr, "FAILED\n");    break;  case RSP_ILLEGAL_BREAKPOINT:    fprintf(stderr, "Illegal breakpoint\n");    break;  case RSP_ILLEGAL_COMMAND:    fprintf(stderr, "Illegal command\n");    break;  case RSP_ILLEGAL_EMULATOR_MODE:    fprintf(stderr, "Illegal emulator mode");    if (len > 1)      switch (data[1]) {      case EMULATOR_MODE_DEBUGWIRE: fprintf(stderr, ": DebugWire"); break;      case EMULATOR_MODE_JTAG:      fprintf(stderr, ": JTAG"); break;      case EMULATOR_MODE_UNKNOWN:   fprintf(stderr, ": Unknown"); break;      case EMULATOR_MODE_SPI:       fprintf(stderr, ": SPI"); break;      }    putc('\n', stderr);    break;  case RSP_ILLEGAL_JTAG_ID:    fprintf(stderr, "Illegal JTAG ID\n");    break;  case RSP_ILLEGAL_MCU_STATE:    fprintf(stderr, "Illegal MCU state");    if (len > 1)      switch (data[1]) {      case STOPPED:     fprintf(stderr, ": Stopped"); break;      case RUNNING:     fprintf(stderr, ": Running"); break;      case PROGRAMMING: fprintf(stderr, ": Programming"); break;      }    putc('\n', stderr);    break;  case RSP_ILLEGAL_MEMORY_TYPE:    fprintf(stderr, "Illegal memory type\n");    break;  case RSP_ILLEGAL_MEMORY_RANGE:    fprintf(stderr, "Illegal memory range\n");    break;  case RSP_ILLEGAL_PARAMETER:    fprintf(stderr, "Illegal parameter\n");    break;  case RSP_ILLEGAL_POWER_STATE:    fprintf(stderr, "Illegal power state\n");    break;  case RSP_ILLEGAL_VALUE:    fprintf(stderr, "Illegal value\n");    break;  case RSP_NO_TARGET_POWER:    fprintf(stderr, "No target power\n");    break;  case RSP_SIGN_ON:    fprintf(stderr, "Sign-on succeeded\n");    /* Sign-on data will be printed below anyway. */    break;  case RSP_MEMORY:    fprintf(stderr, "memory contents:\n");    jtagmkII_print_memory(data, len);    break;  case RSP_PARAMETER:    fprintf(stderr, "parameter values:\n");    jtagmkII_print_memory(data, len);    break;  case RSP_SPI_DATA:    fprintf(stderr, "SPI data returned:\n");    for (i = 1; i < len; i++)      fprintf(stderr, "0x%02x ", data[i]);    putc('\n', stderr);    break;  case EVT_BREAK:    fprintf(stderr, "BREAK event");    if (len >= 6) {      fprintf(stderr, ", PC = 0x%lx, reason ", b4_to_u32(data + 1));      switch (data[5]) {      case 0x00:	fprintf(stderr, "unspecified");	break;      case 0x01:	fprintf(stderr, "program break");	break;      case 0x02:	fprintf(stderr, "data break PDSB");	break;      case 0x03:	fprintf(stderr, "data break PDMSB");	break;      default:	fprintf(stderr, "unknown: 0x%02x", data[5]);      }    }    putc('\n', stderr);    break;  default:    fprintf(stderr, "unknown message 0x%02x\n", data[0]);  }  putc('\n', stderr);}static int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len){  unsigned char *buf;  if (verbose >= 3)    fprintf(stderr, "\n%s: jtagmkII_send(): sending %zd bytes\n",	    progname, len);  if ((buf = malloc(len + 10)) == NULL)    {      fprintf(stderr, "%s: jtagmkII_send(): out of memory",	      progname);      return -1;    }  buf[0] = MESSAGE_START;  u16_to_b2(buf + 1, command_sequence);  u32_to_b4(buf + 3, len);  buf[7] = TOKEN;  memcpy(buf + 8, data, len);  crcappend(buf, len + 8);  if (serial_send(pgm->fd, buf, len + 10) != 0) {    fprintf(stderr,	    "%s: jtagmkII_send(): failed to send command to serial port\n",	    progname);    exit(1);  }  free(buf);  return 0;}static int jtagmkII_drain(PROGRAMMER * pgm, int display){  return serial_drain(pgm->fd, display);}/* * Receive one frame, return it in *msg.  Received sequence number is * returned in seqno.  Any valid frame will be returned, regardless * whether it matches the expected sequence number, including event * notification frames (seqno == 0xffff). * * Caller must eventually free the buffer. */static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg,			       unsigned short * seqno) {  enum states { sSTART,		/* NB: do NOT change the sequence of the following: */		sSEQNUM1, sSEQNUM2,		sSIZE1, sSIZE2, sSIZE3, sSIZE4,		sTOKEN,		sDATA,		sCSUM1, sCSUM2,		/* end NB */		sDONE  }  state = sSTART;  unsigned long msglen = 0, l = 0;  int headeridx = 0;  int timeout = 0;  int ignorpkt = 0;  int rv;  unsigned char c, *buf = NULL, header[8];  unsigned short r_seqno = 0;  unsigned short checksum = 0;  struct timeval tv;  double timeoutval = 5;	/* seconds */  double tstart, tnow;  if (verbose >= 3)    fprintf(stderr, "%s: jtagmkII_recv():\n", progname);  gettimeofday(&tv, NULL);  tstart = tv.tv_sec;  while ( (state != sDONE ) && (!timeout) ) {    if (state == sDATA) {      rv = 0;      if (ignorpkt) {	/* skip packet's contents */	for(l = 0; l < msglen; l++)	  rv += serial_recv(pgm->fd, &c, 1);      } else {	rv += serial_recv(pgm->fd, buf + 8, msglen);      }      if (rv != 0) {	timedout:	/* timeout in receive */	if (verbose > 1)	  fprintf(stderr,		  "%s: jtagmkII_recv(): Timeout receiving packet\n",		  progname);	free(buf);	return -1;      }    } else {      if (serial_recv(pgm->fd, &c, 1) != 0)	goto timedout;    }    checksum ^= c;    if (state < sDATA)      header[headeridx++] = c;    switch (state) {      case sSTART:        if (c == MESSAGE_START) {          state = sSEQNUM1;        } else {	  headeridx = 0;	}        break;      case sSEQNUM1:      case sSEQNUM2:	r_seqno >>= 8;	r_seqno |= ((unsigned)c << 8);	state++;	break;      case sSIZE1:      case sSIZE2:      case sSIZE3:      case sSIZE4:	msglen >>= 8;	msglen |= ((unsigned)c << 24);        state++;        break;      case sTOKEN:        if (c == TOKEN) {	  state = sDATA;	  if (msglen > MAX_MESSAGE) {	    fprintf(stderr,		    "%s: jtagmkII_recv(): msglen %lu exceeds max message "		    "size %u, ignoring message\n",		    progname, msglen, MAX_MESSAGE);	    state = sSTART;	    headeridx = 0;	  } else if ((buf = malloc(msglen + 10)) == NULL) {	    fprintf(stderr, "%s: jtagmkII_recv(): out of memory\n",		    progname);	    ignorpkt++;	  } else {	    memcpy(buf, header, 8);	  }	} else {	  state = sSTART;	  headeridx = 0;	}        break;      case sDATA:	/* The entire payload has been read above. */	l = msglen + 8;        state = sCSUM1;        break;      case sCSUM1:      case sCSUM2:	buf[l++] = c;	if (state == sCSUM2) {	  if (crcverify(buf, msglen + 10)) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?