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 + -
显示快捷键?