You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
piklab/src/progs/direct/base/direct_18F.cpp

319 lines
11 KiB

/***************************************************************************
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
* Copyright (C) 2003-2005 Alain Gibaud <alain.gibaud@free.fr> *
* *
* 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. *
***************************************************************************/
#include "direct_18F.h"
#include "direct_data.h"
//-----------------------------------------------------------------------------
bool Direct::P18F::skipMaskWords(Pic::MemoryRangeType type, const Device::Array &data,
uint &i, uint nb, bool forceProgram)
{
if (forceProgram) return false;
for (uint k=0; k<nb; k++)
if ( data[i+k]!=device().mask(type) ) return false;
i += nb;
return true;
}
void Direct::P18F::program(Type type)
{
TQString cmd;
switch (type) {
case Code:
cmd = TQString("d,C,c,C,c,C,c,Cw%1cw%2X0000,").tqarg(programHighTime(Code)).tqarg(programLowTime());
break;
case Erase:
pulseEngine("k0,X0000,"); // NOP
cmd = TQString("k0;w%1;w%2;X0000").tqarg(programHighTime(type)).tqarg(programLowTime());
break;
case Eeprom:
for (;;) {
pulseEngine("k0,X50A6,");
pulseEngine("k0,X6EF5,");
pulseEngine("k0,X0000,"); // NOP
BitValue b = get_byte();
if ( !b.bit(1) ) break; // WR bit clear
}
cmd = TQString("w%1").tqarg(programLowTime());
break;
}
pulseEngine(cmd);
}
void Direct::P18F::setCodePointer(uint address)
{
pulseEngine("k0,S,k0,X6EF8,", 0x0E00 | ((address & 0xFF0000) >> 16));
pulseEngine("k0,S,k0,X6EF7,", 0x0E00 | ((address & 0x00FF00) >> 8));
pulseEngine("k0,S,k0,X6EF6,", 0x0E00 | (address & 0x0000FF));
}
void Direct::P18F::setPointer(Pic::MemoryRangeType type, uint offset)
{
if ( type==Pic::MemoryRangeType::Eeprom ) {
pulseEngine("k0,S,k0,X6EA9,", 0x0E00 | (offset & 0x00FF));
pulseEngine("k0,S,k0,X6EAA,", 0x0E00 | ((offset & 0xFF00) >> 8));
} else setCodePointer(device().range(type).start.toUInt() + offset);
}
void Direct::P18F::directAccess(Pic::MemoryRangeType type)
{
if ( type==Pic::MemoryRangeType::Code || type==Pic::MemoryRangeType::UserId || type==Pic::MemoryRangeType::Eeprom ) pulseEngine("k0,X9CA6"); // unset EECON1:CFGS
else pulseEngine("k0,X8CA6"); // set EECON1:CFGS
if ( type==Pic::MemoryRangeType::Eeprom ) pulseEngine("k0,X9EA6"); // unset EECON1::EEPGD
else pulseEngine("k0,X8EA6"); // set EECON1::EEPGD
}
bool Direct::P18F::doRead(Pic::MemoryRangeType type, Device::Array &data, const ::Programmer::VerifyData *vdata)
{
data.resize(device().nbWords(type));
uint offset = 0;
uint nbWords = data.count();
if (vdata) {
if ( vdata->actions & ::Programmer::OnlyProgrammedVerify ) {
const Device::Array wdata = static_cast<const Pic::Memory &>(vdata->memory).arrayForWriting(type);
offset = findNonMaskStart(type, wdata);
nbWords = findNonMaskEnd(type, wdata)+1;
}
}
BitValue mask = device().mask(type);
//qDebug("read %s %i", Pic::MEMORY_RANGE_TYPE_DATA[type].label, device().nbWords(type));
//pulseEngine("w300000"); // what for ?
directAccess(type);
switch (type.type()) {
case Pic::MemoryRangeType::Eeprom:
for (uint i = 0; i<data.count(); i++) {
setPointer(type, i);
pulseEngine("k0,X80A6,k0,X50A8,k0,X6EF5,k0,X0000");
data[i] = pulseEngine("r").maskWith(mask);
if ( vdata && !hardware().verifyWord(offset+i, data[i], type, *vdata) ) return false;
}
_base.progressMonitor().addTaskProgress(data.count());
break;
case Pic::MemoryRangeType::Code:
setPointer(type, offset);
//pulseEngine("w1000"); ??
for (uint i=0; i<nbWords; i++) {
data[i] = pulseEngine("R").maskWith(mask);
if ( vdata && !hardware().verifyWord(offset+i, data[i], type, *vdata) ) return false;
}
_base.progressMonitor().addTaskProgress(data.count());
break;
case Pic::MemoryRangeType::UserId:
case Pic::MemoryRangeType::Config:
case Pic::MemoryRangeType::DeviceId:
setPointer(type, 0);
for (uint i = 0; i<data.count(); i+=2) {
BitValue w = pulseEngine("R");
data[i] = w.maskWith(mask);
if ( vdata && !hardware().verifyWord(offset+i, data[i], type, *vdata) ) return false;
data[i+1] = w >> 8;
if ( vdata && !hardware().verifyWord(offset+i+1, data[i+1], type, *vdata) ) return false;
}
break;
default: Q_ASSERT(false); break;
}
return true;
}
bool Direct::P18F::doWrite(Pic::MemoryRangeType type, const Device::Array &data, bool force)
{
uint inc = device().addressIncrement(type);
//qDebug("write %s %i/%i %i", Pic::MEMORY_RANGE_TYPE_DATA[type].label, nbWords, data.count(), inc);
//pulseEngine("w300000"); ??
configureSinglePanel();
directAccess(type);
switch (type.type()) {
case Pic::MemoryRangeType::UserId: {
setPointer(type, 0);
Q_ASSERT( device().nbWords(Pic::MemoryRangeType::UserId)==8 );
uint i = 0;
for (uint k=0; k<4; k++) {
BitValue word = data[i] | data[i+1] << 8;
if ( (k+1)==4 ) pulseEngine("k15,S,", word);
else pulseEngine("k13,S,", word);
i += 2;
}
program(Code);
break;
}
case Pic::MemoryRangeType::Code: {
uint progWidth = device().nbWordsWriteAlignment(Pic::MemoryRangeType::Code);
for (uint i = 0; i<data.count(); ) {
if ( i!=0 && i%0x100==0 ) _base.progressMonitor().addTaskProgress(0x100);
if ( skipMaskWords(type, data, i, progWidth, force) ) continue;
setPointer(type, inc * i);
for (uint k=0; k<progWidth; k++) {
if ( (k+1)==progWidth ) pulseEngine("k15,S,", data[i]);
else pulseEngine("k13,S,", data[i]);
i++;
}
program(Code);
}
_base.progressMonitor().addTaskProgress(data.count()%0x100);
break;
}
case Pic::MemoryRangeType::Config:
pulseEngine("k0,XEF00,k0,XF800,"); // move PC somewhere else (0x100000)
for (uint i = 0; i<data.count(); i+=2) {
setPointer(type, inc * i);
BitValue w = data[i] | (data[i+1] << 8);
pulseEngine("k15,S,", w);
program(Code);
pulseEngine("k0,X2AF6,"); // increment address
pulseEngine("k15,S,", w);
program(Code);
pulseEngine("k0,X0000,"); // NOP: some devices need 4 NOPS here...
pulseEngine("k0,X0000,"); // NOP
pulseEngine("k0,X0000,"); // NOP
pulseEngine("k0,X0000,"); // NOP
}
break;
case Pic::MemoryRangeType::Eeprom:
for(uint i = 0; i<data.count(); ) {
if ( i!=0 && i%0x100==0 ) _base.progressMonitor().addTaskProgress(0x100);
if ( skipMaskWords(type, data, i, 1, force) ) continue;
setPointer(type, inc * i);
pulseEngine("k0,S,k0,X6EA8,", data[i] | 0x0E00); // load data
pulseEngine("k0,X84A6,"); // enable memory writes
unlockEeprom();
pulseEngine("k0,X82A6,"); // write
program(Eeprom);
pulseEngine("k0,X94A6,"); // disable writes
i++;
}
_base.progressMonitor().addTaskProgress(data.count()%0x100);
break;
default: Q_ASSERT(false); break;
}
return true;
}
void Direct::P18F::unlockEeprom()
{
pulseEngine("k0,X0E55,k0,X6EA7,k0,X0EAA,k0,X6EA7,");
}
bool Direct::P18F::doEraseCommand(uint cmd1, uint cmd2)
{
if ( cmd1!=0 ) {
setCodePointer(0x3C0005);
pulseEngine("k12;X" + toHex(cmd1, 4));
}
setCodePointer(0x3C0004);
pulseEngine("k12;X" + toHex(cmd2, 4));
program(Erase);
return true;
}
bool Direct::P18F::doEraseRange(Pic::MemoryRangeType type)
{
if ( type==Pic::MemoryRangeType::Code ) {
doEraseCommand(0, 0x0083); // boot
for (uint i=0; i<device().config().protection().nbBlocks(); i++)
doEraseCommand(0, 0x0088 + i);
return true;
}
if ( type==Pic::MemoryRangeType::Eeprom ) return doEraseCommand(0, 0x0081);
return false;
}
bool Direct::P18F::doErase(bool)
{
return doEraseCommand(0, 0x0080);
}
//-----------------------------------------------------------------------------
void Direct::P18F1220::program(Type type)
{
if ( type==Eeprom ) {
pulseEngine("k0,X0000,"); // NOP
TQString cmd = TQString("k0;w%1;w%2;X0000").tqarg(programHighTime(type)).tqarg(programLowTime());
pulseEngine(cmd);
} else P18F::program(type);
}
//-----------------------------------------------------------------------------
void Direct::P18F242::configureSinglePanel()
{
setCodePointer(0x3C0006);
pulseEngine("k12,X0000");
}
//-----------------------------------------------------------------------------
bool Direct::P18F2539::doErase(bool)
{
// apparently there is no chip erase...
return ( doEraseRange(Pic::MemoryRangeType::Code) && doEraseRange(Pic::MemoryRangeType::Eeprom) );
}
bool Direct::P18F2539::doEraseCommand(uint cmd1, uint cmd2)
{
Q_ASSERT( cmd1==0 );
setCodePointer(0x3C0004);
pulseEngine("k0;X" + toHex(cmd2, 4)); // is that correct ??
program(Erase);
return true;
}
//-----------------------------------------------------------------------------
bool Direct::P18F2439::doEraseRange(Pic::MemoryRangeType type)
{
if ( type==Pic::MemoryRangeType::Code ) {
configureSinglePanel();
directAccess(Pic::MemoryRangeType::Code);
for (uint i=0; i<40; i++) {
setCodePointer(0x200000 + 64*i);
pulseEngine("k0;X84A6;k0;X88A6"); // enable memory writes + setup erase
unlockEeprom();
pulseEngine("k0;X82A6"); // initiate erase
program(Erase);
pulseEngine("k0;X94A6"); // disable memory writes
}
return true;
}
return P18F2539::doEraseRange(type);
}
//-----------------------------------------------------------------------------
bool Direct::P18F2221::doEraseRange(Pic::MemoryRangeType type)
{
if ( type==Pic::MemoryRangeType::Code ) {
doEraseCommand(0, 0x8181); // boot
for (uint i=0; i<device().config().protection().nbBlocks(); i++) {
uint v = (1 << i);
doEraseCommand(v + v<<8, 0x8080);
}
return true;
}
if ( type==Pic::MemoryRangeType::Eeprom ) return doEraseCommand(0, 0x8484);
return false;
}
bool Direct::P18F2221::doErase(bool)
{
return doEraseCommand(0x0F0F, 0x8787); // chip erase
}
//-----------------------------------------------------------------------------
bool Direct::P18F6527::doErase(bool)
{
return doEraseCommand(0xFFFF, 0x8787); // chip erase
}
//-----------------------------------------------------------------------------
bool Direct::P18F6310::doErase(bool)
{
setCodePointer(0x3C0005);
pulseEngine("k12,X010A");
setCodePointer(0x3C0004);
pulseEngine("k12,X018A");
program(Erase);
return true;
}