📄 stk500v2.c
字号:
/* * 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 + -