stk500.c

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

C
1,205
字号
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com> * * 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: stk500.c,v 1.48 2005/08/30 01:30:05 bdean Exp $ *//* * avrdude interface for Atmel STK500 programmer * * Note: most commands use the "universal command" feature of the * programmer in a "pass through" mode, exceptions are "program * enable", "paged read", and "paged write". * */#include "ac_cfg.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include "avr.h"#include "pgm.h"#include "stk500_private.h"#include "serial.h"#define STK500_XTAL 7372800Uextern int    verbose;extern char * progname;extern int do_cycles;static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value);static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value);static void stk500_print_parms1(PROGRAMMER * pgm, char * p);static int stk500_is_page_empty(unsigned int address, int page_size,     const unsigned char *buf);static int stk500_send(PROGRAMMER * pgm, unsigned char * buf, size_t len){  return serial_send(pgm->fd, buf, len);}static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len){  int rv;  rv = serial_recv(pgm->fd, buf, len);  if (rv < 0) {    fprintf(stderr,	    "%s: stk500_recv(): programmer is not responding\n",	    progname);    exit(1);  }  return 0;}static int stk500_drain(PROGRAMMER * pgm, int display){  return serial_drain(pgm->fd, display);}static int stk500_getsync(PROGRAMMER * pgm){  unsigned char buf[32], resp[32];  /*   * get in sync */  buf[0] = Cmnd_STK_GET_SYNC;  buf[1] = Sync_CRC_EOP;  stk500_send(pgm, buf, 2);  stk500_recv(pgm, resp, 1);  if (resp[0] != Resp_STK_INSYNC) {    fprintf(stderr,             "%s: stk500_getsync(): not in sync: resp=0x%02x\n",            progname, resp[0]);    stk500_drain(pgm, 0);    exit(1);  }  stk500_recv(pgm, resp, 1);  if (resp[0] != Resp_STK_OK) {    fprintf(stderr,             "%s: stk500_getsync(): can't communicate with device: "            "resp=0x%02x\n",            progname, resp[0]);    exit(1);  }  return 0;}/* * transmit an AVR device command and return the results; 'cmd' and * 'res' must point to at least a 4 byte data buffer */static int stk500_cmd(PROGRAMMER * pgm, unsigned char cmd[4],                      unsigned char res[4]){  unsigned char buf[32];  buf[0] = Cmnd_STK_UNIVERSAL;  buf[1] = cmd[0];  buf[2] = cmd[1];  buf[3] = cmd[2];  buf[4] = cmd[3];  buf[5] = Sync_CRC_EOP;  stk500_send(pgm, buf, 6);  stk500_recv(pgm, buf, 1);  if (buf[0] != Resp_STK_INSYNC) {    fprintf(stderr, "%s: stk500_cmd(): programmer is out of sync\n", progname);    exit(1);  }  res[0] = cmd[1];  res[1] = cmd[2];  res[2] = cmd[3];  stk500_recv(pgm, &res[3], 1);  stk500_recv(pgm, buf, 1);  if (buf[0] != Resp_STK_OK) {    fprintf(stderr, "%s: stk500_cmd(): protocol error\n", progname);    exit(1);  }  return 0;}/* * issue the 'chip erase' command to the AVR device */static int stk500_chip_erase(PROGRAMMER * pgm, AVRPART * p){  unsigned char cmd[4];  unsigned char res[4];  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {    fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",            p->desc);    return -1;  }  pgm->pgm_led(pgm, ON);  memset(cmd, 0, sizeof(cmd));  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);  pgm->cmd(pgm, cmd, res);  usleep(p->chip_erase_delay);  pgm->initialize(pgm, p);  pgm->pgm_led(pgm, OFF);  return 0;}/* * issue the 'program enable' command to the AVR device */static int stk500_program_enable(PROGRAMMER * pgm, AVRPART * p){  unsigned char buf[16];  int tries=0; retry:    tries++;  buf[0] = Cmnd_STK_ENTER_PROGMODE;  buf[1] = Sync_CRC_EOP;  stk500_send(pgm, buf, 2);  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_NOSYNC) {    if (tries > 33) {      fprintf(stderr, "%s: stk500_program_enable(): can't get into sync\n",              progname);      return -1;    }    stk500_getsync(pgm);    goto retry;  }  else if (buf[0] != Resp_STK_INSYNC) {    fprintf(stderr,            "%s: stk500_program_enable(): protocol error, "            "expect=0x%02x, resp=0x%02x\n",             progname, Resp_STK_INSYNC, buf[0]);    return -1;  }  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_OK) {    return 0;  }  else if (buf[0] == Resp_STK_NODEVICE) {    fprintf(stderr, "%s: stk500_program_enable(): no device\n",            progname);    return -1;  }  if(buf[0] == Resp_STK_FAILED)  {      fprintf(stderr, 	      "%s: stk500_program_enable(): failed to enter programming mode\n", 		  progname);	  return -1;  }  fprintf(stderr, "%s: stk500_program_enable(): unknown response=0x%02x\n",          progname, buf[0]);  return -1;}static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,                                     unsigned char * cmd){  unsigned char buf[16];  int tries=0;  int i; retry:    tries++;  buf[0] = Cmnd_STK_SET_DEVICE_EXT;  for (i=0; i<n; i++) {    buf[1+i] = cmd[i];  }  i++;  buf[i] = Sync_CRC_EOP;  stk500_send(pgm, buf, i+1);  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_NOSYNC) {    if (tries > 33) {      fprintf(stderr, "%s: stk500_set_extended_parms(): can't get into sync\n",              progname);      return -1;    }    stk500_getsync(pgm);    goto retry;  }  else if (buf[0] != Resp_STK_INSYNC) {    fprintf(stderr,            "%s: stk500_set_extended_parms(): protocol error, "            "expect=0x%02x, resp=0x%02x\n",             progname, Resp_STK_INSYNC, buf[0]);    return -1;  }  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_OK) {    return 0;  }  else if (buf[0] == Resp_STK_NODEVICE) {    fprintf(stderr, "%s: stk500_set_extended_parms(): no device\n",            progname);    return -1;  }  if(buf[0] == Resp_STK_FAILED)  {      fprintf(stderr, 	      "%s: stk500_set_extended_parms(): failed to set extended "              "device programming parameters\n",               progname);	  return -1;  }  fprintf(stderr, "%s: stk500_set_extended_parms(): unknown response=0x%02x\n",          progname, buf[0]);  return -1;}/* * initialize the AVR device and prepare it to accept commands */static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p){  unsigned char buf[32];  AVRMEM * m;  int tries;  unsigned maj, min;  int rc;  int n_extparms = 3;  stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj);  stk500_getparm(pgm, Parm_STK_SW_MINOR, &min);  if ((maj > 1) || ((maj == 1) && (min > 10)))    n_extparms = 4;  tries = 0; retry:  tries++;  memset(buf, 0, sizeof(buf));  /*   * set device programming parameters   */  buf[0] = Cmnd_STK_SET_DEVICE;  buf[1] = p->stk500_devcode;  buf[2] = 0; /* device revision */  if ((p->flags & AVRPART_SERIALOK) && (p->flags & AVRPART_PARALLELOK))    buf[3] = 0; /* device supports parallel and serial programming */  else    buf[3] = 1; /* device supports parallel only */  if (p->flags & AVRPART_PARALLELOK) {    if (p->flags & AVRPART_PSEUDOPARALLEL) {      buf[4] = 0; /* pseudo parallel interface */      n_extparms = 0;    }    else {      buf[4] = 1; /* full parallel interface */    }  }#if 0  fprintf(stderr, "%s: stk500_initialize(): n_extparms = %d\n",           progname, n_extparms);#endif      buf[5] = 1; /* polling supported - XXX need this in config file */  buf[6] = 1; /* programming is self-timed - XXX need in config file */  m = avr_locate_mem(p, "lock");  if (m)    buf[7] = m->size;  else    buf[7] = 0;  /*   * number of fuse bytes   */  buf[8] = 0;  m = avr_locate_mem(p, "fuse");  if (m)    buf[8] += m->size;  m = avr_locate_mem(p, "lfuse");  if (m)    buf[8] += m->size;  m = avr_locate_mem(p, "hfuse");  if (m)    buf[8] += m->size;  m = avr_locate_mem(p, "efuse");  if (m)    buf[8] += m->size;  m = avr_locate_mem(p, "flash");  if (m) {    buf[9] = m->readback[0];    buf[10] = m->readback[1];    if (m->paged) {      buf[13] = (m->page_size >> 8) & 0x00ff;      buf[14] = m->page_size & 0x00ff;    }    buf[17] = (m->size >> 24) & 0xff;    buf[18] = (m->size >> 16) & 0xff;    buf[19] = (m->size >> 8) & 0xff;    buf[20] = m->size & 0xff;  }  else {    buf[9]  = 0xff;    buf[10]  = 0xff;    buf[13] = 0;    buf[14] = 0;    buf[17] = 0;    buf[18] = 0;    buf[19] = 0;    buf[20] = 0;  }  m = avr_locate_mem(p, "eeprom");  if (m) {    buf[11] = m->readback[0];    buf[12] = m->readback[1];    buf[15] = (m->size >> 8) & 0x00ff;    buf[16] = m->size & 0x00ff;  }  else {    buf[11] = 0xff;    buf[12] = 0xff;    buf[15] = 0;    buf[16] = 0;  }  buf[21] = Sync_CRC_EOP;  stk500_send(pgm, buf, 22);  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_NOSYNC) {    fprintf(stderr,            "%s: stk500_initialize(): programmer not in sync, resp=0x%02x\n",             progname, buf[0]);    if (tries > 33)      return -1;    stk500_getsync(pgm);    goto retry;    return -1;  }  else if (buf[0] != Resp_STK_INSYNC) {    fprintf(stderr,            "%s: stk500_initialize(): (a) protocol error, "            "expect=0x%02x, resp=0x%02x\n",             progname, Resp_STK_INSYNC, buf[0]);    return -1;  }  stk500_recv(pgm, buf, 1);  if (buf[0] != Resp_STK_OK) {    fprintf(stderr,            "%s: stk500_initialize(): (b) protocol error, "            "expect=0x%02x, resp=0x%02x\n",             progname, Resp_STK_OK, buf[0]);    return -1;  }  if (n_extparms) {    if ((p->pagel == 0) || (p->bs2 == 0)) {      fprintf(stderr,               "%s: please define PAGEL and BS2 signals in the configuration "              "file for part %s\n",               progname, p->desc);    }    else {      buf[0] = n_extparms+1;      /*       * m is currently pointing to eeprom memory if the part has it       */      if (m)        buf[1] = m->page_size;      else        buf[1] = 0;            buf[2] = p->pagel;      buf[3] = p->bs2;            if (n_extparms == 4) {        if (p->reset_disposition == RESET_DEDICATED)          buf[4] = 0;        else          buf[4] = 1;      }            rc = stk500_set_extended_parms(pgm, n_extparms+1, buf);      if (rc) {        fprintf(stderr, "%s: stk500_initialize(): failed\n", progname);        exit(1);      }    }  }  return pgm->program_enable(pgm, p);}static void stk500_disable(PROGRAMMER * pgm){  unsigned char buf[16];  int tries=0; retry:    tries++;  buf[0] = Cmnd_STK_LEAVE_PROGMODE;  buf[1] = Sync_CRC_EOP;  stk500_send(pgm, buf, 2);  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_NOSYNC) {    if (tries > 33) {      fprintf(stderr, "%s: stk500_disable(): can't get into sync\n",              progname);      return;    }    stk500_getsync(pgm);    goto retry;  }  else if (buf[0] != Resp_STK_INSYNC) {    fprintf(stderr,            "%s: stk500_disable(): protocol error, expect=0x%02x, "            "resp=0x%02x\n",             progname, Resp_STK_INSYNC, buf[0]);    return;  }  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_OK) {    return;  }  else if (buf[0] == Resp_STK_NODEVICE) {    fprintf(stderr, "%s: stk500_disable(): no device\n",            progname);    return;  }  fprintf(stderr, "%s: stk500_disable(): unknown response=0x%02x\n",          progname, buf[0]);  return;}static void stk500_enable(PROGRAMMER * pgm){  return;}static int stk500_open(PROGRAMMER * pgm, char * port){  strcpy(pgm->port, port);  if (pgm->baudrate)    pgm->fd = serial_open(port, pgm->baudrate);  else    pgm->fd = serial_open(port, 115200);  /*   * drain any extraneous input   */  stk500_drain(pgm, 0);  stk500_getsync(pgm);  stk500_drain(pgm, 0);  return 0;}static void stk500_close(PROGRAMMER * pgm){  serial_close(pgm->fd);  pgm->fd = -1;}static int stk500_loadaddr(PROGRAMMER * pgm, unsigned int addr){  unsigned char buf[16];  int tries;  tries = 0; retry:  tries++;  buf[0] = Cmnd_STK_LOAD_ADDRESS;  buf[1] = addr & 0xff;  buf[2] = (addr >> 8) & 0xff;  buf[3] = Sync_CRC_EOP;  stk500_send(pgm, buf, 4);  stk500_recv(pgm, buf, 1);  if (buf[0] == Resp_STK_NOSYNC) {    if (tries > 33) {      fprintf(stderr, "%s: stk500_loadaddr(): can't get into sync\n",              progname);      return -1;    }    stk500_getsync(pgm);    goto retry;  }  else if (buf[0] != Resp_STK_INSYNC) {

⌨️ 快捷键说明

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