📄 srec.cpp
字号:
/**************************************************************************
Project: WinAVRIDE Class: Read/Write Motorola SRecord File
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 "srec.h"
#define MAX_LINELEN 16
//---------------------------------------------------------------------------
int __fastcall TSRecord::ReadFile (AnsiString name, unsigned char *buf,
int maxsize)
{
unsigned char line[100];
int address, count, i, temp, checksum, filesize = 0;
bool finished = false, r;
stream = new TFileStream(name, fmOpenRead);
if (stream == NULL) return 0;
while (!finished)
{
if (!ReadLine (line))
{
delete stream;
return 0;
}
if (line[0] == 'S')
{
switch (line[1] - '0')
{
case 0: break; // Header
case 1: r = HexToBin (line + 2, &count, 2);
checksum = count;
if (r) r = HexToBin (line + 4, &address, 4);
checksum += address & 0xff;
checksum += (address >> 8) & 0xff;
if ((address + count - 3) > filesize) filesize = address + count - 3;
if (filesize > maxsize)
{
ErrorMessage ("File exceeds Maximum Size");
finished = true;
filesize = 0;
break;
}
for (i = 0;i < count - 3;i++)
{
if (r) r = HexToBin (line + 8 + (2 * i), &temp, 2);
*(buf + address + i) = (unsigned char)temp;
checksum += temp;
}
if (r) r = HexToBin (line + (2 * count) + 2, &temp, 2);
checksum += temp;
if (!r)
{
filesize = 0;
finished = true;
break;
}
if ((checksum & 0xff)!= 0xff)
{
ErrorMessage ("Checksum Error");
finished = true;
filesize = 0;
break;
}
break;
case 2: r = HexToBin (line + 2, &count, 2);
checksum = count;
if (r) r = HexToBin (line + 4, &address, 6);
checksum += address & 0xff;
checksum += (address >> 8) & 0xff;
checksum += (address >> 16) & 0xff;
if ((address + count - 4) > filesize) filesize = address + count - 4;
if (filesize > maxsize)
{
ErrorMessage ("File exceeds Maximum Size");
finished = true;
filesize = 0;
break;
}
for (i = 0;i < count - 4;i++)
{
if (r) r = HexToBin (line + 10 + (2 * i), &temp, 2);
*(buf + address + i) = (unsigned char)temp;
checksum += temp;
}
if (r) r = HexToBin (line + (2 * count) + 2, &temp, 2);
checksum += temp;
if (!r)
{
filesize = 0;
finished = true;
break;
}
if ((checksum & 0xff) != 0xff)
{
ErrorMessage ("Checksum Error");
finished = true;
filesize = 0;
break;
}
break;
case 3: r = HexToBin (line + 2, &count, 2);
checksum = count;
if (r) r = HexToBin (line + 4, &address, 8);
checksum += address & 0xff;
checksum += (address >> 8) & 0xff;
checksum += (address >> 16) & 0xff;
checksum += (address >> 24) & 0xff;
if ((address + count - 5) > filesize) filesize = address + count - 5;
if (filesize > maxsize)
{
ErrorMessage ("File exceeds Maximum Size");
finished = true;
filesize = 0;
break;
}
for (i = 0;i < count - 5;i++)
{
if (r) r = HexToBin (line + 12 + (2 * i), &temp, 2);
*(buf + address + i) = (unsigned char)temp;
checksum += temp;
}
if (r) r = HexToBin (line + (2 * count) + 2, &temp, 2);
checksum += temp;
if (!r)
{
filesize = 0;
finished = true;
break;
}
if ((checksum & 0xff) != 0xff)
{
ErrorMessage ("Checksum Error");
finished = true;
filesize = 0;
break;
}
break;
case 5: break; // Count of records
case 7: // Starting execution address
case 8:
case 9: finished = true;
}
}
else
{
ErrorMessage ("Illegal Line found");
finished = true;
filesize = 0;
}
}
delete stream;
return filesize;
}
//---------------------------------------------------------------------------
bool __fastcall TSRecord::ReadLine (unsigned char *line)
{
int i;
long temppos;
// Workaround for the missing ReadLine Method
temppos = stream->Position;
if (stream->Read (line, 100) < 1)
{
ErrorMessage ("File Read Operation Failed");
return false;
}
for (i = 0;i < 100;i++)
{
if (*(line + i) == 10)
{
stream->Seek(temppos + i + 1, soFromBeginning);
*(line + i + 1) = 0;
break;
}
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TSRecord::HexToBin (unsigned char *in, int *out, int len)
{
if (!isxdigit (*in) || !isxdigit (*(in + 1)))
{
ErrorMessage ("Illegal Char in File");
return false;
}
*out = 0;
while (len--)
{
*out *= 16;
if (*in <= '9') *out += *in - '0';
else if (*in >= 'A' && *in <= 'F') *out += *in -'A' + 10;
else *out += *in - 'a' + 10;
in++;
}
return true;
}
//---------------------------------------------------------------------------
bool __fastcall TSRecord::WriteFile (AnsiString name, unsigned char *buf,
int size)
{
unsigned char line[100];
int type, i, count, address = 0, pos, checksum;
bool emptyline;
stream = new TFileStream(name, fmCreate);
if (stream == NULL) return false;
type = 1;
if (size > 0xffff) type = 2;
if (size > 0xffffff) type = 3;
stream->Write ("S00600004844521B\r\n", 18); // Write Header
while (size)
{
pos = 2;
line[0] = 'S';
line[1] = (unsigned char)(type + '0');
if (size < MAX_LINELEN) count = size;
else count = MAX_LINELEN;
count += type + 1;
checksum = count + 1;
BinToHex (count + 1, line + pos, 2);
pos += 2;
BinToHex (address, line + pos, (type + 1) * 2);
pos += (type + 1) * 2;
checksum += address & 0xff;
checksum += (address >> 8) & 0xff;
checksum += (address >> 16) & 0xff;
checksum += (address >> 24) & 0xff;
emptyline = true;
for (i = 0;i < (count - (type + 1));i++)
{
if (*(buf + i) != 0xff) emptyline = false;
}
for (i = 0;i < (count - (type + 1));i++)
{
checksum += *buf;
BinToHex ((int)*(buf++), line + pos, 2);
pos += 2;
}
BinToHex (0xff - (checksum & 0xff), line + pos, 2);
pos += 2;
*(line + pos++) = '\r';
*(line + pos++) = '\n';
if (!emptyline) stream->Write (line, pos);
if (size >= MAX_LINELEN) size -= MAX_LINELEN;
else size = 0;
address += MAX_LINELEN;
}
if (type == 1) stream->Write ("S9030000FC\r\n", 12);
else if (type == 2) stream->Write ("S804000000FB\r\n", 14);
else stream->Write ("S70500000000FA\r\n", 16);
delete stream;
return true;
}
//---------------------------------------------------------------------------
void __fastcall TSRecord::BinToHex (int in, unsigned char *out, int len)
{
unsigned char t;
while (len--)
{
t = (unsigned char)(in % 16);
in /= 16;
if (t < 10) t += '0';
else t = (unsigned char)(t - 10 + 'A');
*(out + len) = t;
}
}
//---------------------------------------------------------------------------
void __fastcall TSRecord::ErrorMessage (char *mess)
{
Application->MessageBox (mess, "Error", MB_OK | MB_ICONERROR);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -