📄 stk500.cpp
字号:
/**************************************************************************
Project: WinAVRIDE Class: STK500 Programmer
Copyright (C) 2005 Philipp Schober
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
History
19.Feb 2005 - First Release (V1.0)
****************************************************************************/
#include <vcl.h>
#pragma hdrstop
#include "stk500.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
#define NO_RESPONSE 0
#define STK_OK 0x10
#define STK_FAILED 0x11
#define STK_UNKNOWN 0x12
#define STK_NODEVICE 0x13
#define STK_INSYNC 0x14
#define STK_NOSYNC 0x15
#define ADC_CHANNEL_ERROR 0x16
#define ADC_MEASURE_OK 0x17
#define PWM_CHANNEL_ERROR 0x18
#define PWM_ADJUST_OK 0x19
// STK500 Protocol V2
#define STK500V2_OFFSET 5
#define CMD_SIGN_ON 0x01
#define CMD_SET_PARAMETER 0x02
#define CMD_GET_PARAMETER 0x03
#define CMD_LOAD_ADDRESS 0x06
// SPI Commands
#define CMD_ENTER_PROGMODE_ISP 0x10
#define CMD_LEAVE_PROGMODE_ISP 0x11
#define CMD_CHIP_ERASE_ISP 0x12
#define CMD_PROGRAM_FLASH_ISP 0x13
#define CMD_READ_FLASH_ISP 0x14
#define CMD_PROGRAM_EEPROM_ISP 0x15
#define CMD_READ_EEPROM_ISP 0x16
#define CMD_READ_LOCK_ISP 0x1A
#define CMD_READ_SIGNATURE_ISP 0x1B
#define CMD_READ_OSCCAL_ISP 0x1C
#define CMD_SPI_MULTI 0x1D
// Parallel Commands
#define CMD_ENTER_PROGMODE_PP 0x20
#define CMD_LEAVE_PROGMODE_PP 0x21
#define CMD_CHIP_ERASE_PP 0x22
#define CMD_PROGRAM_FLASH_PP 0x23
#define CMD_READ_FLASH_PP 0x24
#define CMD_PROGRAM_EEPROM_PP 0x25
#define CMD_READ_EEPROM_PP 0x26
#define CMD_PROGRAM_FUSE_PP 0x27
#define CMD_READ_FUSE_PP 0x28
#define CMD_PROGRAM_LOCK_PP 0x29
#define CMD_READ_LOCK_PP 0x2A
#define CMD_READ_SIGNATURE_PP 0x2B
#define CMD_READ_OSCCAL_PP 0x2C
#define CMD_SET_CONTROL_STACK 0x2D
// HV Serial Commands
#define CMD_ENTER_PROGMODE_HVSP 0x30
#define CMD_LEAVE_PROGMODE_HVSP 0x31
#define CMD_CHIP_ERASE_HVSP 0x32
#define CMD_PROGRAM_FLASH_HVSP 0x33
#define CMD_READ_FLASH_HVSP 0x34
#define CMD_PROGRAM_EEPROM_HVSP 0x35
#define CMD_READ_EEPROM_HVSP 0x36
#define CMD_PROGRAM_FUSE_HVSP 0x37
#define CMD_READ_FUSE_HVSP 0x38
#define CMD_PROGRAM_LOCK_HVSP 0x39
#define CMD_READ_LOCK_HVSP 0x3A
#define CMD_READ_SIGNATURE_HVSP 0x3B
#define CMD_READ_OSCCAL_HVSP 0x3C
// Status Responses
#define STATUS_CMD_OK 0x00
#define STATUS_CMD_TOUT 0x80
#define STATUS_RDY_BSY_TOUT 0x81
#define STATUS_SET_PARAM_MISSING 0x82
#define STATUS_CMD_FAILED 0xC0
#define STATUS_CKSUM_ERROR 0xC1
#define STATUS_CMD_UNKNOWN 0xC9
// Parameters
#define PARAM_VTARGET 0x94
#define PARAM_VADJUST 0x95
#define PARAM_OSC_PSCALE 0x96
#define PARAM_OSC_CMATCH 0x97
#define PARAM_SCK_DURATION 0x98
//---------------------------------------------------------------------------
__fastcall TSTK500::TSTK500 (TComponent* Owner)
: TComponent(Owner)
{
Comm = new TRS232Comm (this);
Comm->OnRxChar = OnReceive;
Comm->BaudRate = 115200;
Comm->DataBits = 8;
Comm->Parity = 'N';
Comm->StopBits = 10;
Comm->FlowControl = fcNone;
Comm->NullStriping = false;
Comm->InQSize = 1024;
Comm->OutQSize = 1024;
}
//---------------------------------------------------------------------------
__fastcall TSTK500::~TSTK500 (void)
{
delete Comm;
}
//---------------------------------------------------------------------------
void __fastcall TSTK500::OnReceive (DWORD Count)
{
char buffer[1024];
Comm->Read (rxdata + bytesrx, Count);
if (response == NO_RESPONSE) response = buffer[0];
//rxdata += buffer;
bytesrx += Count;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::CheckPresence (void)
{
char cmd[2];
bool r = true;
if (!Comm->Open ()) return false;
cmd[0] = CMD_SIGN_ON;
if (DoCommandV2 (cmd, 1, 11))
{
if (strstr ((char *)rxdata + 8, "STK500_2") ||
strstr ((char *)rxdata + 8, "AVRISP_2"))
{
protocol = 2;
Comm->Close ();
Sleep (50);
return true;
}
}
else protocol = 1;
if (!GetSync ())
{
Comm->Close ();
return false;
}
cmd[0] = 0x31;
cmd[1] = 0x20;
if (!DoCommand (cmd, 2, 9))
{
ErrorMessage ("Can't Start Communication");
r = false;
}
else
{
if (rxdata[0] != STK_INSYNC)
{
ErrorMessage ("Out of Sync on Presence Check");
r = false;
}
else if (!strstr ((char *)rxdata, "AVR STK"))
{
ErrorMessage ("Invalid Sign on Message");
r = false;
}
else if (rxdata[8] != STK_OK)
{
ErrorMessage ("Status Error on Presence Check");
r = false;
}
}
Comm->Close ();
Sleep (50);
return r;
}
//---------------------------------------------------------------------------
void __fastcall TSTK500::SetPort (AnsiString port)
{
Comm->PortName = port;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::EnablePGM (TChipInfo *chip)
{
char cmd[2];
bool r = true;
if (protocol == 2) return EnablePGMV2 (chip);
if (!StartComm ()) return false;
if (!SetDevParameters (chip)) return false;
Sleep (10);
if (!ChangeSCKLen ()) return false;
Sleep (10);
cmd[0] = 0x50;
cmd[1] = 0x20;
if (!DoCommand (cmd, 2, 2)) r = false;
else
{
if (rxdata[0] != STK_INSYNC) r = false;
else if (rxdata[1] != STK_OK) r = false;
}
return r;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::EnablePGMV2 (TChipInfo *chip)
{
char cmd[16], ctrlstack[33] = {CMD_SET_CONTROL_STACK, 0x0e, 0x1e, 0x0f, 0x1e,
0x2e, 0x3e, 0x2f, 0x3f, 0x4e, 0x5e, 0x4f, 0x5f,
0x6e, 0x7e, 0x6f, 0x7f, 0x66, 0x76, 0x67, 0x77,
0x6a, 0x7a, 0x6b, 0x7b, 0xbe, 0xfd, 0, 1, 0, 0, 0, 0};
if (!StartComm ()) return false;
SetDevParameters (chip);
if (!ChangeSCKLenV2 ()) return false;
if (ChipInfoV2.progtype == CHIP_PROGSPI)
{
cmd[0] = CMD_ENTER_PROGMODE_ISP;
cmd[1] = 200; // 200ms Command Timeout
cmd[2] = 100; // 100ms Pin Stab Delay
cmd[3] = 25; // Command Exe Delay
cmd[4] = 32; // Sync Loops
cmd[5] = 0; // Byte Delay
cmd[6] = 0x53; // Poll Value
cmd[7] = 3; // Poll Index
cmd[8] = 0xAC; // Programming Enable
cmd[9] = 0x53;
cmd[10] = 0;
cmd[11] = 0;
if (!DoCommandV2 (cmd, 12, 2)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_ENTER_PROGMODE_ISP) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
}
else
{
if (!DoCommandV2 (ctrlstack, 33, 2)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_SET_CONTROL_STACK) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
if (ChipInfoV2.hvserial)
{
cmd[0] = CMD_ENTER_PROGMODE_HVSP;
cmd[1] = 100; // Pin Stab Delay
cmd[2] = 0; // Command Exe Delay
cmd[3] = 10; // Sync Clock Cycles
cmd[4] = 6; // Latch Cycles
cmd[5] = 0; // Toggle Vtg
cmd[6] = 0; // Power Off Delay
cmd[7] = 0; // Reset Delay 1
cmd[8] = 0; // Reset Delay 2
if (!DoCommandV2 (cmd, 9, 2)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_ENTER_PROGMODE_HVSP) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
}
else
{
cmd[0] = CMD_ENTER_PROGMODE_PP;
cmd[1] = 100; // Pin Stab Delay
cmd[2] = 0; // Command Exe Delay
cmd[3] = 6; // XTAL Cycles to Latch OSCCAL
cmd[4] = 0; // Toggle Vtg
cmd[5] = 0; // Power Off Delay
cmd[6] = 0; // Reset Delay 1
cmd[7] = 0; // Reset Delay 2
if (!DoCommandV2 (cmd, 8, 2)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_ENTER_PROGMODE_PP) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
}
}
return true;
}
//---------------------------------------------------------------------------
void __fastcall TSTK500::DisablePGM (void)
{
char cmd[2];
int i;
bool r = true;
if (protocol == 2)
{
DisablePGMV2 ();
return;
}
cmd[0] = 0x51;
cmd[1] = 0x20;
for (i = 0;i < 10;i++)
{
if (!DoCommand (cmd, 2, 2)) r = false;
else
{
if (rxdata[0] != STK_INSYNC) r = false;
else if (rxdata[1] != STK_OK) r = false;
}
if (r) break;
else r = true;
}
StopComm ();
}
//---------------------------------------------------------------------------
void __fastcall TSTK500::DisablePGMV2 (void)
{
char cmd[3];
if (ChipInfoV2.progtype == CHIP_PROGSPI) cmd[0] = CMD_LEAVE_PROGMODE_ISP;
else if (ChipInfoV2.hvserial) cmd[0] = CMD_LEAVE_PROGMODE_HVSP;
else cmd[0] = CMD_LEAVE_PROGMODE_PP;
cmd[1] = 1; // Pre Delay (ms)
cmd[2] = 1; // Post Delay (ms)
DoCommandV2 (cmd, 3, 2);
StopComm ();
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::DoCommand (unsigned char *com, int len, int num)
{
int i;
bytesrx = 0;
Comm->Write (com, len);
for (i = 0;i < 100;i++)
{
Application->ProcessMessages ();
Sleep (5);
if (bytesrx >= num)
{
return true;
}
}
return false;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::DoCommandV2 (unsigned char *com, int len, int num)
{
int i;
unsigned char temp[400] = {0}, ChkSum;
static unsigned char SeqNum = 0;
// Prepare Message
temp[0] = 0x1b;
temp[1] = SeqNum++;
temp[3] = (unsigned char)(len & 0xff);
temp[2] = (unsigned char)((len >> 8) & 0xff);
temp[4] = 0x0e;
ChkSum = temp[0];
for (i = 1;i < 5;i++) ChkSum ^= temp[i];
for (i = 0;i < len;i++)
{
temp[5 + i] = *(com + i);
ChkSum ^= temp[5 + i];
}
temp[5 + i] = ChkSum;
bytesrx = 0;
Comm->Write (temp, len + 6);
for (i = 0;i < 100;i++)
{
Application->ProcessMessages ();
Sleep (5);
if (bytesrx >= num + 6)
{
rxdata[bytesrx] = 0;
return true;
}
}
return false;
}
//---------------------------------------------------------------------------
void __fastcall TSTK500::ErrorMessage (AnsiString msg)
{
Application->MessageBox (msg.c_str(), "Error", MB_OK | MB_ICONERROR);
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::GetSignature (unsigned char *sig)
{
char cmd[2];
bool r = true;
if (protocol == 2) return GetSignatureV2 (sig);
cmd[0] = 0x75;
cmd[1] = 0x20;
if (!DoCommand (cmd, 2, 5))
{
ErrorMessage ("Can't Start Communication");
r = false;
}
else
{
if (rxdata[0] != STK_INSYNC)
{
ErrorMessage ("Out of Sync on Get Signature");
r = false;
}
else if (rxdata[4] != STK_OK)
{
ErrorMessage ("Status Error on Get Signature");
r = false;
}
}
//Comm->Close ();
*(sig++) = rxdata[1];
*(sig++) = rxdata[2];
*sig = rxdata[3];
return r;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::GetSignatureV2 (unsigned char *sig)
{
char cmd[6];
if (ChipInfoV2.progtype == CHIP_PROGSPI)
{ // SPI Mode
cmd[0] = CMD_READ_SIGNATURE_ISP;
cmd[1] = 4; // Return Address
cmd[2] = 0x30; // Read Signature Byte
cmd[3] = 0;
cmd[5] = 0;
for (cmd[4] = 0;cmd[4] < 3;cmd[4]++)
{
if (!DoCommandV2 (cmd, 6, 4)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_READ_SIGNATURE_ISP) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
*(sig++) = rxdata[STK500V2_OFFSET + 2];
}
}
else
{ // High Voltage Serial/Parallel Mode
if (ChipInfoV2.hvserial) cmd[0] = CMD_READ_SIGNATURE_HVSP;
else cmd[0] = CMD_READ_SIGNATURE_PP;
for (cmd[1] = 0;cmd[1] < 3;cmd[1]++)
{
if (!DoCommandV2 (cmd, 2, 3)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_READ_SIGNATURE_PP &&
rxdata[STK500V2_OFFSET] != CMD_READ_SIGNATURE_HVSP) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
*(sig++) = rxdata[STK500V2_OFFSET + 2];
}
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::SetDevParameters (TChipInfo *chip)
{
unsigned char cmd[22];
bool r = true;
union {int val; unsigned char byte[4];} conv;
int i;
if (protocol == 2)
{
for (i = 0;i < sizeof(TChipInfo);i++)
{
*((unsigned char *)&ChipInfoV2 + i) = *((unsigned char *)chip + i);
}
return true;
}
cmd[0] = 0x42;
cmd[1] = chip->stk500_dev;
cmd[2] = 0; // Revision
cmd[3] = chip->progtype;
cmd[4] = chip->parmode;
cmd[5] = 0; //No Polling
cmd[6] = chip->selftimed;
cmd[7] = chip->lockbytes;
cmd[8] = chip->fusebytes;
cmd[9] = 0xFF; //Flashpolval1
cmd[10] = 0xFF; //Flashpolval2
cmd[11] = 0; //EEPROMpolval1
cmd[12] = 0xFF; //EEPROMpolval2;
conv.val = chip->pagesize;
cmd[13] = conv.byte[1];
cmd[14] = conv.byte[0];
conv.val = chip->eepromsize;
cmd[15] = conv.byte[1];
cmd[16] = conv.byte[0];
conv.val = chip->flashsize;
cmd[17] = conv.byte[3];
cmd[18] = conv.byte[2];
cmd[19] = conv.byte[1];
cmd[20] = conv.byte[0];
cmd[21] = 0x20;
if (!DoCommand (cmd, 22, 2)) r = false;
else
{
if (rxdata[0] != STK_INSYNC) r = false;
else if (rxdata[1] != STK_OK) r = false;
}
return r;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::GetSync (void)
{
unsigned char cmd[2];
cmd[0] = 0x30;
cmd[1] = 0x20;
if (!DoCommand (cmd, 2, 2)) return false;
else
{
if (rxdata[0] != STK_INSYNC) return false;
else if (rxdata[1] != STK_OK) return false;
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::LoadAddress (int adr)
{
unsigned char cmd[4];
if (protocol == 2) return LoadAddressV2 (adr);
cmd[0] = 0x55;
cmd[1] = adr & 0xff;
cmd[2] = (adr >> 8) & 0xff;
cmd[3] = 0x20;
if (!DoCommand (cmd, 4, 2)) return false;
else
{
if (rxdata[0] != STK_INSYNC) return false;
else if (rxdata[1] != STK_OK) return false;
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TSTK500::LoadAddressV2 (int adr)
{
unsigned char cmd[5];
cmd[0] = CMD_LOAD_ADDRESS;
cmd[1] = (adr >> 24) & 0xff;
cmd[2] = (adr >> 16) & 0xff;
cmd[3] = (adr >> 8) & 0xff;
cmd[4] = adr & 0xff;
if (!DoCommandV2 (cmd, 5, 2)) return false;
if (rxdata[STK500V2_OFFSET] != CMD_LOAD_ADDRESS) return false;
if (rxdata[STK500V2_OFFSET + 1] != STATUS_CMD_OK) return false;
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -