⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ihex.cpp

📁 用于开发Atmel的AVR系列单片机的GCC集成开发环境
💻 CPP
字号:
/**************************************************************************
Project: WinAVRIDE        Class: Read/Write Intel Hex
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 "ihex.h"

#define MAX_LINELEN 32 // Has to be 2,4,8,16,32,...
//---------------------------------------------------------------------------
int __fastcall TIHex::ReadFile (AnsiString name, unsigned char *buf,
                                    int maxsize)
{
 unsigned char line[512];
 int offset, linoffs, segoffs, addr, reclen, i, temp, checksum, filesize = 0;
 int rectype;
 bool finished = false, r;

 stream = new TFileStream(name, fmOpenRead);
 if (stream == NULL) return 0;
 linoffs = segoffs = 0;
 while (!finished)
 {
  if (!ReadLine (line))
  {
   delete stream;
   ErrorMessage ("Error reading File");
   return 0;
  }
  if (line[0] == ':')
  {
   r = HexToBin (line + 1, &reclen, 2);
   if (r) r = HexToBin (line + 3, &offset, 4);
   if (r) r = HexToBin (line + 7, &rectype, 2);
   if (!r)
   {
    delete stream;
    return 0;
   }
   checksum = reclen + rectype;
   checksum += (unsigned char)(offset & 0xff);
   checksum += (unsigned char)((offset >> 8)& 0xff);
   switch (rectype)
   {
    case 0: // Data Record
            addr = offset + linoffs + segoffs;
    	    if ((addr + reclen) > filesize) filesize = addr + reclen;
            if (filesize > maxsize)
            {
             ErrorMessage ("File exceeds Maximum Size");
             filesize = 0;
             finished = true;
             break;
            }
            for (i = 0;i < reclen;i++)
            {
             if (r) r = HexToBin (line + 9 + (2 * i), &temp, 2);
             *(buf + addr + i) = (unsigned char)temp;
             checksum += (unsigned char)temp;
            }
            if (r) r = HexToBin (line + 9 + (2 * i), &temp, 2);
            checksum += (unsigned char)temp;
            if (!r)
            {
             finished = true;
             filesize = 0;
             break;
            }
            if ((checksum & 0xff)!= 0)
            {
             ErrorMessage ("Checksum Error type 0");
             filesize = 0;
             finished = true;
            }
            break;
    case 1: // End of File Record
            r = HexToBin (line + 9, &temp, 2);
    	    if (!r)
            {
             finished = true;
             filesize = 0;
             break;
            }
            if (reclen != 0 || offset != 0 || temp != 0xff)
            {
             ErrorMessage ("Invalid EOF Record");
             filesize = 0;
            }
            finished = true;
            break;
    case 2: // Extended Segment Address Record
            if (reclen != 2)
            {
             ErrorMessage ("Invalid Record Length for type 2");
             filesize = 0;
             finished = true;
             break;
            }
            r = HexToBin (line + 9, &segoffs, 4);
            if (r) r = HexToBin (line + 13, &temp, 2);
            checksum += (unsigned char)(segoffs & 0xff);
            checksum += (unsigned char)((segoffs >> 8) & 0xff);
            checksum += (unsigned char)temp;
            if (!r)
            {
             finished = true;
             filesize = 0;
             break;
            }
            if ((checksum & 0xff)!= 0)
            {
             ErrorMessage ("Checksum Error type 2");
             filesize = 0;
             finished = true;
            }
            segoffs <<= 4;
            break;
    case 3: // Start Segment Address Record
            break;
    case 4: // Extended Linear Address Record
            if (reclen != 2)
            {
             ErrorMessage ("Invalid Record Length for type 4");
             filesize = 0;
             finished = true;
             break;
            }
            r = HexToBin (line + 9, &linoffs, 4);
            if (r) r = HexToBin (line + 13, &temp, 2);
            checksum += (unsigned char)(linoffs & 0xff);
            checksum += (unsigned char)((linoffs >> 8) & 0xff);
            checksum += (unsigned char)temp;
            if (!r)
            {
             finished = true;
             filesize = 0;
             break;
            }
            if ((checksum & 0xff)!= 0)
            {
             ErrorMessage ("Checksum Error type 4");
             filesize = 0;
             finished = true;
            }
            linoffs <<= 16;
            break;
    case 5: // Start Linear Address Record
            break;
    default: ErrorMessage ("Invalid Record type");
    	     filesize = 0;
    	     finished = true;
             break;
   }
  }
  else
  {
   ErrorMessage ("Illegal Line found");
   filesize = 0;
   finished = true;
  }
 }
 delete stream;
 return filesize;
}
//---------------------------------------------------------------------------
bool __fastcall TIHex::ReadLine (unsigned char *line)
{
 int i;
 long temppos;

 // Workaround for the missing ReadLine Method
 temppos = stream->Position;
 if (stream->Read (line, 512) < 1)
 {
  ErrorMessage ("File Read Operation Failed");
  return false;
 }
 for (i = 0;i < 512;i++)
 {
  if (*(line + i) == 10)
  {
   stream->Seek(temppos + i + 1, soFromBeginning);
   *(line + i + 1) = 0;
   break;
  }
 }

 return true;
}
//---------------------------------------------------------------------------
bool __fastcall TIHex::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 TIHex::WriteFile (AnsiString name, unsigned char *buf,
        						     int size)
{
 unsigned char line[512];
 int i, len, address = 0, pos, checksum, linoffs = 0, offset;
 bool emptyline;
 stream = new TFileStream(name, fmCreate);
 if (stream == NULL) return false;

 while (size)
 {
  if ((address - linoffs) > 0xffff)
  {
   linoffs = address & 0xffff0000;
   line[0] = ':';
   BinToHex (2, line + 1, 2);
   BinToHex (0, line + 3, 4);
   BinToHex (4, line + 7, 2);
   BinToHex (linoffs >> 16, line + 9, 4);
   checksum = 6 + ((linoffs >> 16) & 0xff) + ((linoffs >> 24) & 0xff);
   checksum = 0x100 - (checksum & 0xff);
   BinToHex (checksum & 0xff, line + 13, 2);
   line[15] = '\r';
   line[16] = '\n';
   stream->Write (line, 17);
  }
  line[0] = ':';
  if (size < MAX_LINELEN) len = size;
  else len = MAX_LINELEN;
  BinToHex (len, line + 1, 2);
  checksum = len;
  pos = 3;
  offset = address - linoffs;
  BinToHex (offset, line + pos, 4);
  checksum += ((offset >> 8) & 0xff);
  checksum += (offset & 0xff);
  pos += 4;
  BinToHex (0, line + pos, 2);
  pos += 2;
  emptyline = true;
  for (i = 0;i < len;i++)
  {
   checksum += *(buf + address + i);
   if (*(buf + address + i) != 0xff) emptyline = false;
   BinToHex ((int)*(buf + address + i), line + pos, 2);
   pos += 2;
  }
  checksum = 0x100 - (checksum & 0xff);
  BinToHex (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;
 }
 stream->Write (":00000001FF\r\n", 13); // Write EOF Record
 delete stream;
 return true;
}
//---------------------------------------------------------------------------
void __fastcall TIHex::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 TIHex::ErrorMessage (char *mess)
{
 Application->MessageBox (mess, "Error", MB_OK | MB_ICONERROR);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -