ponyprog/SrcPony/pic12bus.cpp

599 lines
12 KiB
C++
Raw Normal View History

2004-11-30 17:46:48 +00:00
//=========================================================================//
// //
// PonyProg - Serial Device Programmer //
// //
2017-04-18 01:25:22 +02:00
// Copyright (C) 1997-2017 Claudio Lanconelli //
2004-11-30 17:46:48 +00:00
// //
// http://ponyprog.sourceforge.net //
2004-11-30 17:46:48 +00:00
// //
//-------------------------------------------------------------------------//
// //
// 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 version2 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 (see COPYING); if not, write to the //
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
// //
//-------------------------------------------------------------------------//
//=========================================================================//
#include "types.h"
#include "pic12bus.h"
#include "errcode.h"
2017-04-18 01:25:22 +02:00
#include <QDebug>
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
#include "e2cmdw.h"
#ifdef __linux__
2008-01-10 23:12:55 +00:00
//# include <asm/io.h>
2004-11-30 17:46:48 +00:00
# include <unistd.h>
#else
2017-04-18 01:25:22 +02:00
# ifdef __BORLANDC__
# define __inline__
2004-11-30 17:46:48 +00:00
# else // _MICROSOFT_ VC++
2017-04-18 01:25:22 +02:00
# define __inline__ __inline
2004-11-30 17:46:48 +00:00
# define _export
# endif
#endif
2017-04-18 01:25:22 +02:00
#define MAX_PROG_PULSES 8
2004-11-30 17:46:48 +00:00
// Constructor
Pic12Bus::Pic12Bus(BusInterface *ptr)
: BusIO(ptr),
2017-04-18 01:25:22 +02:00
// DataMask(0xff),
ProgMask(0x0fff), //12bit instruction
ReadProgCode(0x04), //Read Data from Program Memory *
LoadProgCode(0x02), //Load Data for Program Memory *
// ReadDataCode(0x05), //Read Data from Data Memory *
// LoadDataCode(0x03), //Load Data for Data Memory *
// LoadConfigCode(0x00), //Load Configuration *
IncAddressCode(0x06), //Increment Address *
// EraseProgMem(0x09), //Bulk Erase Program Memory *
// EraseDataMem(0x0b), //Bulk Erase Data Memory *
BeginProgCode(0x08), //Begin Erase Programming Cycle *
// BeginProgOnlyCode(0x18) //Begin Programming Only Cycle
EndProgCode(0x0e)
2004-11-30 17:46:48 +00:00
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Pic12Bus()";
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
OverProgrammingMult = 11; //Default OverProgramming X value (x11)
OverProgrammingAdd = 0; //Default OverProgramming + value (+0)
2004-11-30 17:46:48 +00:00
}
// Desctructor
Pic12Bus::~Pic12Bus()
{
2017-04-18 01:25:22 +02:00
// Close();
2004-11-30 17:46:48 +00:00
}
void Pic12Bus::SetDelay()
{
2017-04-18 01:25:22 +02:00
int val = E2Profile::GetPICSpeed();
2009-11-15 13:33:22 +00:00
int n;
2017-04-29 01:56:50 +02:00
switch (val)
2009-11-15 13:33:22 +00:00
{
case TURBO:
n = 1;
break;
2017-04-18 01:25:22 +02:00
case FAST:
n = 3;
break;
2017-04-18 01:25:22 +02:00
case SLOW:
n = 20;
break;
2017-04-18 01:25:22 +02:00
case VERYSLOW:
n = 100;
break;
2017-04-18 01:25:22 +02:00
case ULTRASLOW:
n = 1000;
break;
2017-04-18 01:25:22 +02:00
default:
n = 8; //Default (< 100KHz)
break;
2009-11-15 13:33:22 +00:00
}
2017-04-18 01:25:22 +02:00
2009-11-15 13:33:22 +00:00
BusIO::SetDelay(n);
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
qDebug() << "PIC12Bus::SetDelay() = " << n;
2004-11-30 17:46:48 +00:00
}
int Pic12Bus::SendDataBit(int b)
{
2017-04-18 01:25:22 +02:00
setCLK(); //set SCK high
2004-11-30 17:46:48 +00:00
bitDI(b);
WaitUsec(shot_delay);
2017-04-18 01:25:22 +02:00
clearCLK(); //device latch data bit now!
2004-11-30 17:46:48 +00:00
WaitUsec(shot_delay);
return OK;
}
// returns a negative number in case of error, 0 or 1 otherwise
int Pic12Bus::RecDataBit()
{
2009-11-16 22:29:18 +00:00
register uint8_t b;
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
setCLK(); //set SCK high (Pic output data now)
2004-11-30 17:46:48 +00:00
WaitUsec(shot_delay);
2017-04-18 01:25:22 +02:00
b = getDO(); // sampling data on falling edge
2004-11-30 17:46:48 +00:00
clearCLK();
WaitUsec(shot_delay);
return b;
}
// OK, ora ci alziamo di un livello: operiamo sul byte
int Pic12Bus::SendDataWord(long wo, int wlen)
{
int k;
clearCLK();
clearDI();
//transmit lsb first
for (k = 0; k < wlen; k++)
2017-04-18 01:25:22 +02:00
{
SendDataBit(wo & (1 << k));
}
2004-11-30 17:46:48 +00:00
setDI();
//1 usec from a command to the next
2017-04-18 01:25:22 +02:00
WaitUsec(shot_delay / 4 + 1);
2004-11-30 17:46:48 +00:00
return OK;
}
long Pic12Bus::RecDataWord(int wlen)
{
int k;
long val = 0;
clearCLK();
setDI();
//receive lsb first
for (k = 0; k < wlen; k++)
2017-04-29 01:56:50 +02:00
if (RecDataBit())
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
val |= 1 << k;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
WaitUsec(shot_delay / 4 + 1);
2004-11-30 17:46:48 +00:00
return val;
}
int Pic12Bus::Reset(void)
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Reset() IN";
2004-11-30 17:46:48 +00:00
SetDelay();
2017-04-18 01:25:22 +02:00
SetMCLR(); //First bogus entry to charge capacitors
WaitMsec(200); //150
2004-11-30 17:46:48 +00:00
clearDI();
2017-04-18 01:25:22 +02:00
ClearMCLR(); //Now reset the micro
setCLK(); //keep Vdd on
2004-11-30 17:46:48 +00:00
WaitMsec(20);
2017-04-18 01:25:22 +02:00
clearCLK(); //Prepare for Program mode entry
2004-11-30 17:46:48 +00:00
WaitMsec(10);
2017-04-18 01:25:22 +02:00
SetMCLR(); //Program mode entry
2004-11-30 17:46:48 +00:00
WaitMsec(10);
current_address = -1;
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Reset() OUT";
2004-11-30 17:46:48 +00:00
return OK;
}
long Pic12Bus::ReadConfig(uint16_t &data)
2004-11-30 17:46:48 +00:00
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::ReadConfig(" << (hex) << data << (dec) << ") IN";
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
// Reset();
2004-11-30 17:46:48 +00:00
2009-11-16 22:29:18 +00:00
uint8_t *bp = (uint8_t *)&data;
2004-11-30 17:46:48 +00:00
2009-11-15 13:33:22 +00:00
//Read Program Code
2004-11-30 17:46:48 +00:00
SendCmdCode(ReadProgCode);
uint16_t val = RecvProgCode();
2004-11-30 17:46:48 +00:00
if (val == ProgMask)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
val = 0xffff;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
#ifdef _BIG_ENDIAN_
2009-11-16 22:29:18 +00:00
*bp++ = (uint8_t)(val >> 8);
*bp++ = (uint8_t)(val & 0xFF);
2004-11-30 17:46:48 +00:00
#else
2009-11-16 22:29:18 +00:00
*bp++ = (uint8_t)(val & 0xFF);
*bp++ = (uint8_t)(val >> 8);
2004-11-30 17:46:48 +00:00
#endif
IncAddress(1);
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::ReadConfig(" << (hex) << data << (dec) << ") OUT";
2004-11-30 17:46:48 +00:00
return OK;
}
2017-04-18 01:25:22 +02:00
long Pic12Bus::WriteConfig(uint16_t data)
2004-11-30 17:46:48 +00:00
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteConfig(" << (hex) << data << (dec) << ") IN";
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
// Reset();
2004-11-30 17:46:48 +00:00
2009-11-16 22:29:18 +00:00
uint8_t *bp = (uint8_t *)&data;
uint16_t val;
2004-11-30 17:46:48 +00:00
//Write Program code
2017-04-18 01:25:22 +02:00
#ifdef _BIG_ENDIAN_
val = (uint16_t)(*bp++) << 8;
val |= (uint16_t)(*bp++);
2004-11-30 17:46:48 +00:00
#else
val = (uint16_t)(*bp++);
val |= (uint16_t)(*bp++) << 8;
2004-11-30 17:46:48 +00:00
#endif
int k;
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
for (k = 100; k > 0; k--)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
ProgramPulse(val, 0);
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
IncAddress(1);
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteConfig(" << (hex) << data << (dec) << ") OUT";
2004-11-30 17:46:48 +00:00
return OK;
}
long Pic12Bus::BlankCheck(long length)
{
2017-04-18 01:25:22 +02:00
length >>= 1; //contatore da byte a word
2004-11-30 17:46:48 +00:00
ReadStart();
2009-11-15 13:33:22 +00:00
//Point to first location
2017-04-18 01:25:22 +02:00
// SendCmdCode(IncAddressCode);
2004-11-30 17:46:48 +00:00
long len;
2017-04-18 01:25:22 +02:00
for (len = 0; len < length - 1; len++) //Skip last location (RC calibration)
2004-11-30 17:46:48 +00:00
{
//Read Program Code
SendCmdCode(ReadProgCode);
2017-04-18 01:25:22 +02:00
2017-04-29 01:56:50 +02:00
if (CompareSingleWord(0xffff, RecvProgCode(), ProgMask))
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
if (ReadProgress(len * 100 / length))
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
2009-11-15 13:33:22 +00:00
IncAddress(1);
2004-11-30 17:46:48 +00:00
}
2017-04-18 01:25:22 +02:00
ReadEnd();
2004-11-30 17:46:48 +00:00
return (len == length);
}
2009-11-16 22:29:18 +00:00
long Pic12Bus::Read(int addr, uint8_t *data, long length, int page_size)
2004-11-30 17:46:48 +00:00
{
long len;
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Read(" << addr << ", " << (hex) << data << ", " << (dec) << length << ") IN";
ReadStart();
2017-04-18 01:25:22 +02:00
length >>= 1; //contatore da byte a word
2004-11-30 17:46:48 +00:00
2009-11-15 13:33:22 +00:00
//Point to first location
2017-04-18 01:25:22 +02:00
// SendCmdCode(IncAddressCode);
2004-11-30 17:46:48 +00:00
for (len = 0; len < length; len++)
{
//Read Program Code
SendCmdCode(ReadProgCode);
uint16_t val = RecvProgCode();
2004-11-30 17:46:48 +00:00
if (val == ProgMask)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
val = 0xffff;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
#ifdef _BIG_ENDIAN_
2009-11-16 22:29:18 +00:00
*data++ = (uint8_t)(val >> 8);
*data++ = (uint8_t)(val & 0xFF);
2004-11-30 17:46:48 +00:00
#else
2009-11-16 22:29:18 +00:00
*data++ = (uint8_t)(val & 0xFF);
*data++ = (uint8_t)(val >> 8);
2004-11-30 17:46:48 +00:00
#endif
IncAddress(1);
if (ReadProgress(len * 100 / length))
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
}
2017-04-18 01:25:22 +02:00
ReadEnd();
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
len <<= 1; //contatore da word a byte
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Read() = " << len << " OUT";
2004-11-30 17:46:48 +00:00
return len;
}
2009-11-16 22:29:18 +00:00
long Pic12Bus::Write(int addr, uint8_t const *data, long length, int page_size)
2004-11-30 17:46:48 +00:00
{
long len;
int rv = OK;
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Write(" << addr << ", " << (hex) << data << ", " << (dec) << length << ") IN";
WriteStart();
2017-04-18 01:25:22 +02:00
length >>= 1; //contatore da byte a word
2004-11-30 17:46:48 +00:00
//The address pointer should already point to first address
//location (via a ConfigRead or IncAddress)
//Program cycle
for (len = 0; len < length; len++)
{
uint16_t val;
2004-11-30 17:46:48 +00:00
//Write Program code
2017-04-18 01:25:22 +02:00
#ifdef _BIG_ENDIAN_
val = (uint16_t)(*data++) << 8;
val |= (uint16_t)(*data++);
2004-11-30 17:46:48 +00:00
#else
val = (uint16_t)(*data++);
val |= (uint16_t)(*data++) << 8;
2004-11-30 17:46:48 +00:00
#endif
2017-04-18 01:25:22 +02:00
rv = WriteProgWord(val, length - 1);
2004-11-30 17:46:48 +00:00
2017-04-29 01:56:50 +02:00
if (rv != OK)
2004-11-30 17:46:48 +00:00
{
len = rv;
break;
2009-11-15 13:33:22 +00:00
}
2004-11-30 17:46:48 +00:00
if (WriteProgress(len * 100 / length))
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
}
2017-04-18 01:25:22 +02:00
WriteEnd();
2004-11-30 17:46:48 +00:00
if (len > 0)
2017-04-18 01:25:22 +02:00
{
len <<= 1; //contatore da word a byte
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::Write() = " << len << " ** " << GetLastProgrammedAddress() << " OUT";
2004-11-30 17:46:48 +00:00
return len;
}
int Pic12Bus::WriteProgWord(uint16_t val, long rc_addr)
2004-11-30 17:46:48 +00:00
{
int k;
int rval = OK;
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteProgWord(" << (hex) << val << ", " << (dec) << current_address << ") IN";
2004-11-30 17:46:48 +00:00
//Check for RC calibration location
if (current_address == rc_addr)
{
//Check for blank (erased cells)
//Programma la RC calibration solamente se la locazione e` cancellata
// e il valore da pgrogrammare corrisponde ad una MOVLW xx (0x0Cxx)
SendCmdCode(ReadProgCode);
2017-04-18 01:25:22 +02:00
2017-04-29 01:56:50 +02:00
if (CompareSingleWord(RecvProgCode(), 0xffff, ProgMask) == 0 &&
CompareSingleWord(val, 0x0C00, (ProgMask & 0xff00)) == 0)
{
SetLastProgrammedAddress(current_address << 1);
2004-11-30 17:46:48 +00:00
for (k = 1; k <= MAX_PROG_PULSES; k++)
{
2017-04-29 01:56:50 +02:00
if (ProgramPulse(val, 1) == OK)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
}
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
if (k > MAX_PROG_PULSES)
{
2017-04-18 01:25:22 +02:00
rval = E2ERR_WRITEFAILED; //Write error
2004-11-30 17:46:48 +00:00
}
else
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteProgWord(): Npulses = " << k;
2004-11-30 17:46:48 +00:00
k *= OverProgrammingMult;
k += OverProgrammingAdd;
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
while (k--)
2017-04-18 01:25:22 +02:00
{
ProgramPulse(val, 0); //Program pulse without test
}
2004-11-30 17:46:48 +00:00
}
2009-11-15 13:33:22 +00:00
}
2004-11-30 17:46:48 +00:00
IncAddress(1);
}
else
{
//Check for blank (erased cells)
SendCmdCode(ReadProgCode);
2017-04-18 01:25:22 +02:00
2017-04-29 01:56:50 +02:00
if (CompareSingleWord(RecvProgCode(), 0xffff, ProgMask))
2004-11-30 17:46:48 +00:00
{
rval = E2ERR_BLANKCHECKFAILED;
}
else
{
//Skip FFF words
2017-04-29 01:56:50 +02:00
if (CompareSingleWord(val, 0xffff, ProgMask) != 0)
2004-11-30 17:46:48 +00:00
{
SetLastProgrammedAddress(current_address << 1);
2004-11-30 17:46:48 +00:00
for (k = 1; k <= MAX_PROG_PULSES; k++)
{
2017-04-29 01:56:50 +02:00
if (ProgramPulse(val, 1) == OK)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
break;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
}
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
if (k > MAX_PROG_PULSES)
{
2017-04-18 01:25:22 +02:00
rval = E2ERR_WRITEFAILED; //Write error
2004-11-30 17:46:48 +00:00
}
else
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteProgWord(): Npulses = " << k;
2004-11-30 17:46:48 +00:00
k *= OverProgrammingMult;
k += OverProgrammingAdd;
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
while (k--)
2017-04-18 01:25:22 +02:00
{
ProgramPulse(val, 0); //Program pulse without test
}
2004-11-30 17:46:48 +00:00
}
}
IncAddress(1);
}
2009-11-15 13:33:22 +00:00
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::WriteProgWord() = " << rval << " OUT";
2004-11-30 17:46:48 +00:00
return rval;
}
void Pic12Bus::IncAddress(int n)
{
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::IncAddress(" << n << ") IN";
2004-11-30 17:46:48 +00:00
while (n--)
{
SendCmdCode(IncAddressCode);
current_address++;
}
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::IncAddress() OUT ** cur_addr = " << current_address;
2004-11-30 17:46:48 +00:00
}
int Pic12Bus::ProgramPulse(uint16_t val, int verify, int width)
2004-11-30 17:46:48 +00:00
{
int rval = OK;
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::ProgramPulse(" << (hex) << val << ", " << (dec) << verify << ", " << width << ") IN";
2004-11-30 17:46:48 +00:00
SendCmdCode(LoadProgCode);
SendProgCode(val);
2017-04-18 01:25:22 +02:00
SendCmdCode(BeginProgCode); //Start programming pulse
2004-11-30 17:46:48 +00:00
WaitUsec(width);
2017-04-18 01:25:22 +02:00
SendCmdCode(EndProgCode); //Stop programming pulse
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
WaitUsec(1000); //wait between pulses
2004-11-30 17:46:48 +00:00
//Verify programmed location
if (verify)
{
SendCmdCode(ReadProgCode);
rval = CompareSingleWord(val, RecvProgCode(), ProgMask);
2009-11-15 13:33:22 +00:00
}
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
qDebug() << "Pic12Bus::ProgramPulse() = " << rval << " OUT";
2004-11-30 17:46:48 +00:00
return rval;
}
int Pic12Bus::CompareSingleWord(uint16_t data1, uint16_t data2, uint16_t mask)
2004-11-30 17:46:48 +00:00
{
return (data1 & mask) != (data2 & mask);
}
int Pic12Bus::CompareMultiWord(uint8_t *data1, uint8_t *data2, long length, int split)
2004-11-30 17:46:48 +00:00
{
int retval = 0;
2017-04-29 01:56:50 +02:00
if (data1 == 0 || data2 == 0 || (length & 1) != 0)
2017-04-18 01:25:22 +02:00
{
2004-11-30 17:46:48 +00:00
return BADPARAM;
2017-04-18 01:25:22 +02:00
}
2004-11-30 17:46:48 +00:00
if (!split)
{
long k;
2017-04-18 01:25:22 +02:00
2004-11-30 17:46:48 +00:00
for (k = 0; k < length; k += 2)
{
uint16_t val1, val2;
2004-11-30 17:46:48 +00:00
2017-04-18 01:25:22 +02:00
#ifdef _BIG_ENDIAN_
val1 = (uint16_t)(*data1++) << 8;
val1 |= (uint16_t)(*data1++);
2004-11-30 17:46:48 +00:00
val2 = (uint16_t)(*data2++) << 8;
val2 |= (uint16_t)(*data2++);
2004-11-30 17:46:48 +00:00
#else
val1 = (uint16_t)(*data1++);
val1 |= (uint16_t)(*data1++) << 8;
2004-11-30 17:46:48 +00:00
val2 = (uint16_t)(*data2++);
val2 |= (uint16_t)(*data2++) << 8;
2004-11-30 17:46:48 +00:00
#endif
2017-04-18 01:25:22 +02:00
2017-04-29 01:56:50 +02:00
if ((retval = CompareSingleWord(val1, val2, ProgMask)))
2017-04-18 01:25:22 +02:00
{
break; //Stop if a difference
}
2004-11-30 17:46:48 +00:00
}
}
else
{
retval = memcmp(data1, data2, length);
}
return retval;
}