📄 stk500.c
字号:
// $Id: Stk500.C,v 1.4.2.1 2003/08/18 22:09:46 cssharp Exp $/* * $Id: Stk500.C,v 1.4.2.1 2003/08/18 22:09:46 cssharp 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 linesconst 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 */TByteTStk500::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 */voidTStk500::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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -