📄 stk500.c
字号:
// $Id: Stk500.C,v 1.4 2006/12/12 18:23:01 vlahan Exp $
/*
* $Id: Stk500.C,v 1.4 2006/12/12 18:23:01 vlahan Exp $
*
****************************************************************************
*
* uisp - The Micro In-System Programmer for Atmel AVR microcontrollers.
* Copyright (C) 2001, 2002, 2003 Daniel Berntsson
*
* 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
*
****************************************************************************
*/
/* Stk500.C, Daniel Berntsson, 2001 */
#include <stdlib.h>
#include "config.h"
#include "Stk500.h"
#include "Serial.h"
const TByte TStk500::pSTK500[] = { 0x30, 0x20 };
const TByte TStk500::pSTK500_Reply[] = { 0x14, 0x10 };
const TByte TStk500::SWminor[] = { 0x41, 0x82, 0x20 };
const TByte TStk500::SWminor_Reply[] = { 0x14, 0x07, 0x10 };
const TByte TStk500::SWmajor[] = { 0x41, 0x81, 0x20 };
const TByte TStk500::SWmajor_Reply[] = {0x14, 0x01, 0x10 };
//XBOW MIC510 cmd to enter cmd MIB510 to take control of RS232 lines
const TByte TStk500::IspMode[] = {0xaa, 0x55, 0x55, 0xaa, 0x17, 0x51, 0x31, 0x13, '?' };
const TByte TStk500::IspMode_Reply[] = { 0x14, 0x10 };
const TByte TStk500::EnterPgmMode[] = { 0x50, 0x20 };
const TByte TStk500::EnterPgmMode_Reply[] = { 0x14, 0x10 };
const TByte TStk500::LeavePgmMode[] = { 0x51, 0x20 };
const TByte TStk500::LeavePgmMode_Reply[] = { 0x14, 0x10 };
const TByte TStk500::SetAddress[] = { 0x55, '?', '?', 0x20 };
const TByte TStk500::SetAddress_Reply[] = { 0x14, 0x10 };
const TByte TStk500::EraseDevice[] = { 0x52, 0x20 };
const TByte TStk500::EraseDevice_Reply[] = { 0x14, 0x10 };
const TByte TStk500::WriteMemory[] = { 0x64, '?', '?', '?' };
const TByte TStk500::WriteMemory_Reply[] = { 0x14, 0x10 };
const TByte TStk500::ReadMemory[] = { 0x74, 0x01, 0x00, '?', 0x20 };
const TByte TStk500::ReadMemory_Reply[] = { 0x14 };
const TByte TStk500::GetSignature[] = {0x75, 0x20};
const TByte TStk500::GetSignature_Reply[] = {0x75, '?', '?', '?', 0x20};
const TByte TStk500::CmdStopByte[] = { 0x20 };
const TByte TStk500::ReplyStopByte[] = { 0x10 };
const TByte TStk500::Flash = 'F';
const TByte TStk500::EEPROM = 'E';
const TByte TStk500::DeviceParam_Reply[] = { 0x14, 0x10 };
const TByte TStk500::ExtDevParams_Reply[] = { 0x14, 0x10 };
/* FIXME: troth/2002-10-02: Get rid of all these magic numbers now that we
know what they mean. (See REAME.stk500) */
TStk500::SPrgPart TStk500::prg_part[] = {
{"AT90S4414",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x50, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x7f, 0x7f, 0x80,
0x7f, {0x00, 0x00}, {0x01, 0x00}, {0x00, 0x00, 0x10, 0x00}, 0x20}
},
{"AT90S2313",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x40, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x7f, 0x7f, 0x80,
0x7f, {0x00, 0x00}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"AT90S1200",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x33, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x00, 0x40}, {0x00, 0x00, 0x04, 0x00}, 0x20}
},
{"AT90S2323",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"AT90S2343",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"AT90S2333",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x42, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"AT90S4433",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x51, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x01, 0x00}, {0x00, 0x00, 0x10, 0x00}, 0x20}
},
{"AT90S4434",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x52, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x01, 0x00}, {0x00, 0x00, 0x10, 0x00}, 0x20}
},
{"AT90S8515",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x60, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x7f, 0x7f, 0x80,
0x7f, {0x00, 0x00}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"AT90S8535",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x61, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"AT90S8534", /* NOTE (20030216): experimental and untested */
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x62, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"ATmega8515",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x63, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x40}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"ATmega8535",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x64, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x40}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"ATtiny11",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00, 0x04, 0x00}, 0x20}
},
{"ATtiny12",
{0x00, 0xD7, 0xA0, 0x01},
{0x42, 0x12, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xff, 0xff, 0xff,
0xff, {0x00, 0x00}, {0x00, 0x40}, {0x00, 0x00, 0x04, 0x00}, 0x20}
},
{"ATtiny15",
{0x00, 0xD7, 0xA0, 0x01},
{0x42, 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xff, 0xff, 0xff,
0xff, {0x00, 0x00}, {0x00, 0x40}, {0x00, 0x00, 0x04, 0x00}, 0x20}
},
{"ATtiny22",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0xff, 0xff, 0x00,
0xff, {0x00, 0x00}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"ATtiny26",
{0x04, 0xD7, 0xA0, 0x01},
{0x42, 0x21, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x20}, {0x00, 0x80}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"ATtiny28",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x22, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00, 0x08, 0x00}, 0x20}
},
{"ATmega8",
{0x04, 0xD7, 0xA0, 0x01},
{0x42, 0x70, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x40}, {0x02, 0x00}, {0x00, 0x00, 0x20, 0x00}, 0x20}
},
{"ATmega323",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x90, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x04, 0x00}, {0x00, 0x00, 0x80, 0x00}, 0x20}
},
{"ATmega32",
{0x04, 0xD7, 0xA0, 0x00},
{0x42, 0x91, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x04, 0x00}, {0x00, 0x00, 0x80, 0x00}, 0x20}
},
// FIXME: add mega64
{"ATmega161",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x80, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x02, 0x00}, {0x00, 0x00, 0x40, 0x00}, 0x20}
},
{"ATmega163",
{0x00, 0xD7, 0xA0, 0x00},
{0x42, 0x81, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x02, 0x00}, {0x00, 0x00, 0x40, 0x00}, 0x20}
},
{"ATmega16",
{0x04, 0xD7, 0xA0, 0x00},
{0x42, 0x82, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x02, 0x00}, {0x00, 0x00, 0x40, 0x00}, 0x20}
},
{"ATmega162",
{0x04, 0xD7, 0xA0, 0x00},
{0x42, 0x83, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x02, 0x00}, {0x00, 0x00, 0x40, 0x00}, 0x20}
},
{"ATmega169",
{0x04, 0xD7, 0xA0, 0x01},
{0x42, 0x84, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff,
0xff, {0x00, 0x80}, {0x02, 0x00}, {0x00, 0x00, 0x40, 0x00}, 0x20}
},
{"ATmega103",
{0x00, 0xA0, 0xD7, 0x00},
{0x42, 0xb1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
0x00, {0x01, 0x00}, {0x10, 0x00}, {0x00, 0x02, 0x00, 0x00}, 0x20}
},
{"ATmega128",
{0x08, 0xD7, 0xA0, 0x00},
{0x42, 0xb2, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff,
0xff, {0x01, 0x00}, {0x10, 0x00}, {0x00, 0x02, 0x00, 0x00}, 0x20}
},
// FIXME: add at86rf401, at89s51, at89s52
{"", {0,0,0,0},{0,0,0,0, 0,0,0,0, 0,0,0,0, 0, {0}, {0}, {0}, 0}}
};
/* Get a stk500 parameter value */
TByte
TStk500::ReadParam(TByte param)
{
TByte buf[0x80];
TByte rd_param[] = { 0x41, param, 0x20 };
TByte rd_param_reply[] = { 0x14, '?', 0x10 };
memcpy(buf, rd_param, sizeof(rd_param));
Send(buf, sizeof(rd_param), sizeof(rd_param_reply));
if ((buf[0] != rd_param_reply[0]) || (buf[2] != rd_param_reply[2]))
{
throw Error_Device ("Failed to read parameter", pNodename);
}
return buf[1];
}
/* Set a stk500 parameter value */
void
TStk500::WriteParam(TByte param, TByte val)
{
TByte buf[0x80];
TByte wr_param[] = { 0x40, param, val, 0x20 };
TByte wr_param_reply[] = { 0x14, 0x10 };
memcpy(buf, wr_param, sizeof(wr_param));
Send(buf, sizeof(wr_param), sizeof(wr_param_reply));
if (memcmp(buf, wr_param_reply, sizeof(wr_param_reply)) != 0)
{
throw Error_Device ("Failed to write parameter", pNodename);
}
}
/* Read byte from active segment at address addr. */
TByte TStk500::ReadByte(TAddr addr)
{
TByte val = 0xff;
if (segment == SEG_FUSE)
{
switch (addr)
{
case AVR_FUSE_LOW_ADDR:
if (TestFeatures(AVR_FUSE_RD))
val = ReadFuseLowBits();
else
Info (1, "Cannot read low fuse bits on this device. "
"Returning 0xff\n");
break;
case AVR_FUSE_HIGH_ADDR:
if (TestFeatures(AVR_FUSE_HIGH))
val = ReadFuseHighBits();
else
Info (1, "Cannot read high fuse bits on this device. "
"Returning 0xff\n");
break;
case AVR_CAL_ADDR:
if (TestFeatures(AVR_CAL_RD))
val = ReadCalFuseBits(0);
else
Info (1, "Cannot read calibration byte on this device. "
"Returning 0xff\n");
break;
case AVR_LOCK_ADDR:
val = ReadLockBits();
break;
case AVR_FUSE_EXT_ADDR:
if (TestFeatures(AVR_FUSE_EXT))
val = ReadFuseExtBits();
else
Info (1, "Cannot read extended fuse bits on this device. "
"Returning 0xff\n");
break;
}
}
else
{
/* FIXME: TRoth/2002-05-29: This is still broken. If flash or eeprom
changes after the calling ReadMem(), you won't ever see the change. */
// Xbow: the original STK500 version reads all 128K of Atmega memory
// before checking. This takes ~15sec on the mib510. This version reads
// a 256 byte page. If a new 256 byte page is needed then it retreives
// it from the mib510
if (read_buffer[segment] == NULL) {
page = addr >> 8; //page number
read_buffer[segment] = new TByte[GetSegmentSize()]; //create buffer for data
ReadMemPage(addr & 0xfff00); //read the page
}
int new_page = addr >> 8;
if (new_page != page){
page = new_page;
ReadMemPage(addr & 0xfff00);
}
val = read_buffer[segment][addr];
}
return val;
}
/* Write byte to active segment */
void TStk500::WriteByte(TAddr addr, TByte byte, bool flush_buffer)
{
if (segment == SEG_FUSE)
{
switch (addr)
{
case AVR_FUSE_LOW_ADDR:
if (TestFeatures(AVR_FUSE_RD))
WriteFuseLowBits(byte);
else
Info (1, "Cannot write low fuse bits on this device.\n");
break;
case AVR_FUSE_HIGH_ADDR:
if (TestFeatures(AVR_FUSE_HIGH))
WriteFuseHighBits(byte);
else
Info (1, "Cannot write high fuse bits on this device.\n");
break;
case AVR_CAL_ADDR:
/* Calibration byte is always readonly. */
break;
case AVR_LOCK_ADDR:
WriteLockBits(byte);
break;
case AVR_FUSE_EXT_ADDR:
if (TestFeatures(AVR_FUSE_EXT))
WriteFuseExtBits(byte);
else
Info (1, "Cannot read extended fuse bits on this device.\n");
break;
}
}
else
{
if (write_buffer[segment] == NULL) {
write_buffer[segment] = new TByte[GetSegmentSize()];
minaddr = GetSegmentSize();
memset(write_buffer[segment], 0xff, GetSegmentSize());
}
if (addr > maxaddr)
maxaddr = addr;
if (addr < minaddr)
minaddr = addr;
write_buffer[segment][addr] = byte;
if (flush_buffer) {
FlushWriteBuffer();
}
}
}
void TStk500::FlushWriteBuffer(){
TByte buf[0x200];
int wordsize;
TAddr addr;
TByte seg;
const TByte *pgsz;
int pagesize;
if (segment == SEG_FLASH) {
wordsize = 2;
seg = Flash;
} else {
wordsize = 1;
seg = EEPROM;
}
pgsz = prg_part[desired_part].params.pagesize;
pagesize = (pgsz[0]) << 8 + pgsz[1];
if (pagesize == 0) {
pagesize = 128;
}
EnterProgrammingMode();
addr = 0;
for (unsigned int addr=minaddr; addr<maxaddr; addr+=pagesize) {
memcpy(buf, SetAddress, sizeof(SetAddress));
buf[1] = (addr/wordsize) & 0xff;
buf[2] = ((addr/wordsize) >> 8) & 0xff;
Send(buf, sizeof(SetAddress), sizeof(SetAddress_Reply));
if (memcmp(buf, SetAddress_Reply, sizeof(SetAddress_Reply)) != 0) {
throw Error_Device ("[FWB 1] Device is not responding correctly.", pNodename); }
memcpy(buf, WriteMemory, sizeof(WriteMemory));
buf[1] = pagesize >> 8;
buf[2] = pagesize & 0xff;
buf[3] = seg;
memcpy(buf+sizeof(WriteMemory), write_buffer[segment]+addr, pagesize);
memcpy(buf+sizeof(WriteMemory)+pagesize,
CmdStopByte, sizeof(CmdStopByte));
Send(buf, sizeof(WriteMemory)+pagesize+sizeof(CmdStopByte),
sizeof(WriteMemory_Reply));
if (memcmp(buf, WriteMemory_Reply, sizeof(WriteMemory_Reply)) != 0) {
throw Error_Device ("[FWB 2] Device is not responding correctly.", pNodename); }
}
LeaveProgrammingMode();
}
/* Chip Erase */
void TStk500::ChipErase(){
TByte buf[100];
EnterProgrammingMode();
memcpy(buf, EraseDevice, sizeof(EraseDevice));
Send(buf, sizeof(EraseDevice), sizeof(EraseDevice_Reply));
if (memcmp(buf, EraseDevice_Reply, sizeof(EraseDevice_Reply)) != 0) {
throw Error_Device ("[CE] Device is not responding correctly.", pNodename); }
LeaveProgrammingMode();
}
TByte TStk500::ReadLockFuseBits()
{
TByte cmd[] = { 0x58, 0x00, 0x00, 0x00 };
return UniversalCmd(cmd);
}
/* ReadLockBits tries to return the lock bits in a uniform order, despite the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -