⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stk500v2.c

📁 这是一个非常有价值的参考代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2005 Erik Walthinsen * 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: stk500v2.c,v 1.8 2005/09/16 21:23:14 bdean Exp $ *//* Based on Id: stk500.c,v 1.46 2004/12/22 01:52:45 bdean Exp *//* * avrdude interface for Atmel STK500V2 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 <sys/time.h>#include <time.h>#include "avr.h"#include "pgm.h"#include "stk500_private.h"	// temp until all code converted#include "stk500v2_private.h"#include "serial.h"#define STK500V2_XTAL 7372800U#if 0#define DEBUG(format,args...) fprintf(stderr, format, ## args)#else#define DEBUG(format,args...)#endif#if 0#define DEBUGRECV(format,args...) fprintf(stderr, format, ## args)#else#define DEBUGRECV(format,args...)#endifextern int    verbose;extern char * progname;extern int do_cycles;static unsigned char command_sequence = 1;static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value);static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p);static int stk500v2_is_page_empty(unsigned int address, int page_size,                                  const unsigned char *buf);static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len){  unsigned char buf[275 + 6];		// max MESSAGE_BODY of 275 bytes, 6 bytes overhead  int i;  buf[0] = MESSAGE_START;  buf[1] = command_sequence;  buf[2] = len / 256;  buf[3] = len % 256;  buf[4] = TOKEN;  memcpy(buf+5, data, len);  // calculate the XOR checksum  buf[5+len] = 0;  for (i=0;i<5+len;i++)    buf[5+len] ^= buf[i];  DEBUG("STK500V2: stk500v2_send(");  for (i=0;i<len+6;i++) DEBUG("0x%02x ",buf[i]);  DEBUG(", %d)\n",len+6);  if (serial_send(pgm->fd, buf, len+6) != 0) {    fprintf(stderr,"%s: stk500_send(): failed to send command to serial port\n",progname);    exit(1);  }  return 0;}static int stk500v2_drain(PROGRAMMER * pgm, int display){  return serial_drain(pgm->fd, display);}static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {  enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE }  state = sSTART;  int msglen = 0;  int curlen = 0;  int timeout = 0;  unsigned char c, checksum = 0;  long timeoutval = 5;		// seconds  struct timeval tv;  double tstart, tnow;  DEBUG("STK500V2: stk500v2_recv(): ");  gettimeofday(&tv, NULL);  tstart = tv.tv_sec;  while ( (state != sDONE ) && (!timeout) ) {    if (serial_recv(pgm->fd, &c, 1) < 0)      goto timedout;    DEBUG("0x%02x ",c);    checksum ^= c;    switch (state) {      case sSTART:        DEBUGRECV("hoping for start token...");        if (c == MESSAGE_START) {          DEBUGRECV("got it\n");          checksum = MESSAGE_START;          state = sSEQNUM;        } else          DEBUGRECV("sorry\n");        break;      case sSEQNUM:        DEBUGRECV("hoping for sequence...\n");        if (c == command_sequence) {          DEBUGRECV("got it, incrementing\n");          state = sSIZE1;          command_sequence++;        } else {          DEBUGRECV("sorry\n");          state = sSTART;        }        break;      case sSIZE1:        DEBUGRECV("hoping for size LSB\n");        msglen = c*256;        state = sSIZE2;        break;      case sSIZE2:        DEBUGRECV("hoping for size MSB...");        msglen += c;        DEBUG(" msg is %d bytes\n",msglen);        state = sTOKEN;        break;      case sTOKEN:        if (c == TOKEN) state = sDATA;        else state = sSTART;        break;      case sDATA:        if (curlen < maxsize) {          msg[curlen] = c;        } else {          fprintf(stderr, "%s: stk500v2_recv(): buffer too small, received %d byte into %zd byte buffer\n",                  progname,curlen,maxsize);          return -2;        }        if ((curlen == 0) && (msg[0] == ANSWER_CKSUM_ERROR)) {          fprintf(stderr, "%s: stk500v2_recv(): previous packet sent with wrong checksum\n",                  progname);          return -3;        }        curlen++;        if (curlen == msglen) state = sCSUM;        break;      case sCSUM:        if (checksum == 0) {          state = sDONE;        } else {          state = sSTART;          fprintf(stderr, "%s: stk500v2_recv(): checksum error\n",                  progname);          return -4;        }        break;      default:        fprintf(stderr, "%s: stk500v2_recv(): unknown state\n",                progname);        return -5;     } /* switch */     gettimeofday(&tv, NULL);     tnow = tv.tv_sec;     if (tnow-tstart > timeoutval) {			// wuff - signed/unsigned/overflow      timedout:       fprintf(stderr, "%s: stk500_2_ReceiveMessage(): timeout\n",               progname);       return -1;     }  } /* while */  DEBUG("\n");  return msglen+6;}static int stk500v2_getsync(PROGRAMMER * pgm) {  int tries = 0;  unsigned char buf[1], resp[32];  int status;  DEBUG("STK500V2: stk500v2_getsync()\n");retry:  tries++;  // send the sync command and see if we can get there  buf[0] = CMD_SIGN_ON;  stk500v2_send(pgm, buf, 1);  // try to get the response back and see where we got  status = stk500v2_recv(pgm, resp, sizeof(resp));  // if we got bytes returned, check to see what came back  if (status > 0) {    if ((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK)) {      // success!      return 0;    } else {      if (tries > 33) {        fprintf(stderr,                "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",                progname, resp[0]);        return -6;      } else        goto retry;    }  // or if we got a timeout  } else if (status == -1) {    if (tries > 33) {      fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n",              progname);      return -1;    } else      goto retry;  // or any other error  } else {    if (tries > 33) {      fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",              progname,status);    } else      goto retry;  }  return 0;}static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf, size_t len, size_t maxlen) {  int i;  int tries = 0;  int status;  DEBUG("STK500V2: stk500v2_command(");  for (i=0;i<len;i++) DEBUG("0x%02hhx ",buf[i]);  DEBUG(", %d)\n",len);retry:  tries++;  // send the command to the programmer  stk500v2_send(pgm,buf,len);  // attempt to read the status back  status = stk500v2_recv(pgm,buf,maxlen);  // if we got a successful readback, return  if (status > 0) {    DEBUG(" = %d\n",status);    return status;  }  // otherwise try to sync up again  status = stk500v2_getsync(pgm);  if (status != 0) {    if (tries > 33) {      fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",              progname,buf[0]);      return -1;    } else      goto retry;  }  DEBUG(" = 0\n");  return 0;}static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],                        unsigned char res[4]){  unsigned char buf[8];  int result;  DEBUG("STK500V2: stk500v2_cmd(%02x,%02x,%02x,%02x)\n",cmd[0],cmd[1],cmd[2],cmd[3]);  buf[0] = CMD_SPI_MULTI;  buf[1] = 4;  buf[2] = 4;  buf[3] = 0;  buf[4] = cmd[0];  buf[5] = cmd[1];  buf[6] = cmd[2];  buf[7] = cmd[3];  result = stk500v2_command(pgm, buf, 8, sizeof(buf));  if (buf[1] != STATUS_CMD_OK) {    fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n",            progname);    return -1;  }  res[0] = buf[2];  res[1] = buf[3];  res[2] = buf[4];  res[3] = buf[5];  return 0;}/* * issue the 'chip erase' command to the AVR device */static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p){  int result;  unsigned char buf[16];  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {    fprintf(stderr, "%s: stk500v2_chip_erase: chip erase instruction not defined for part \"%s\"\n",            progname, p->desc);    return -1;  }  pgm->pgm_led(pgm, ON);  buf[0] = CMD_CHIP_ERASE_ISP;  buf[1] = p->chip_erase_delay / 1000;  buf[2] = 0;	// use delay (?)  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], buf+3);  result = stk500v2_command(pgm, buf, 7, sizeof(buf));  usleep(p->chip_erase_delay);  pgm->initialize(pgm, p);  pgm->pgm_led(pgm, OFF);  return result;}/* * issue the 'program enable' command to the AVR device */static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p){  unsigned char buf[16];  if (p->op[AVR_OP_PGM_ENABLE] == NULL) {    fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n",            progname, p->desc);    return -1;  }  buf[0] = CMD_ENTER_PROGMODE_ISP;  buf[1] = p->timeout;  buf[2] = p->stabdelay;  buf[3] = p->cmdexedelay;  buf[4] = p->synchloops;  buf[5] = p->bytedelay;  buf[6] = p->pollvalue;  buf[7] = p->pollindex;  avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8);  return stk500v2_command(pgm, buf, 12, sizeof(buf));}/* * initialize the AVR device and prepare it to accept commands */static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p){  return pgm->program_enable(pgm, p);}static void stk500v2_disable(PROGRAMMER * pgm){  unsigned char buf[16];  int result;  buf[0] = CMD_LEAVE_PROGMODE_ISP;  buf[1] = 1; // preDelay;  buf[2] = 1; // postDelay;  result = stk500v2_command(pgm, buf, 3, sizeof(buf));  if (buf[1] != STATUS_CMD_OK) {    fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n",            progname,buf[1]);    exit(1);  }  return;}static void stk500v2_enable(PROGRAMMER * pgm){  return;}static int stk500v2_open(PROGRAMMER * pgm, char * port){  DEBUG("STK500V2: stk500v2_open()\n");  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   */  stk500v2_drain(pgm, 0);  stk500v2_getsync(pgm);  stk500v2_drain(pgm, 0);  return 0;}static void stk500v2_close(PROGRAMMER * pgm){  DEBUG("STK500V2: stk500v2_close()\n");  serial_close(pgm->fd);  pgm->fd = -1;}static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr){  unsigned char buf[16];  int result;  DEBUG("STK500V2: stk500v2_loadaddr(%d)\n",addr);  buf[0] = CMD_LOAD_ADDRESS;  buf[1] = (addr >> 24) & 0xff;  buf[2] = (addr >> 16) & 0xff;  buf[3] = (addr >> 8) & 0xff;  buf[4] = addr & 0xff;  result = stk500v2_command(pgm, buf, 5, sizeof(buf));  if (buf[1] != STATUS_CMD_OK) {    fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n",            progname,buf[1]);    return -1;  }  return 0;}

⌨️ 快捷键说明

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