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.
347 lines
11 KiB
347 lines
11 KiB
/***************************************************************************
|
|
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
|
|
* Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com> *
|
|
* *
|
|
* 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 "psp.h"
|
|
|
|
#include "common/global/global.h"
|
|
#include "common/common/misc.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
TQMemArray<uchar> Psp::createConfigInfo(const Pic::Data &data)
|
|
{
|
|
TQMemArray<uchar> array(33);
|
|
array.fill(0x00);
|
|
|
|
const Pic::Config &config = data.config();
|
|
for (uint i=0; i<uint(config._words.count()); i++) {
|
|
BitValue v = config._words[i].usedMask();
|
|
if ( data.nbBytesWord(Pic::MemoryRangeType::UserId)==1 ) array[i ^ 1] = v.byte(0);
|
|
else {
|
|
array[2*i] = v.byte(1);
|
|
array[2*i + 1] = v.byte(0);
|
|
}
|
|
}
|
|
for (uint i=0; i<16; i++) array[i + 16] = array[i];
|
|
|
|
// checksum
|
|
for (uint i=0; i<32; i++) array[32] += array[i];
|
|
|
|
return array;
|
|
}
|
|
|
|
TQMemArray<uchar> Psp::createDeviceInfo(const Pic::Data &data)
|
|
{
|
|
TQMemArray<uchar> config = createConfigInfo(data);
|
|
TQMemArray<uchar> array(45);
|
|
array.fill(0x00);
|
|
|
|
// memory code length
|
|
BitValue v = data.nbWords(Pic::MemoryRangeType::Code);
|
|
array[0] = v.byte(1);
|
|
array[1] = v.byte(0);
|
|
// address word width
|
|
v = data.mask(Pic::MemoryRangeType::Code);
|
|
array[2] = v.byte(1);
|
|
array[3] = v.byte(0);
|
|
// data word width
|
|
array[4] = v.byte(1);
|
|
array[5] = v.byte(0);
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::UserId) ) {
|
|
// user id width
|
|
v = data.userIdRecommendedMask();
|
|
if ( data.nbBytesWord(Pic::MemoryRangeType::UserId)==1 ) v += v << 8;
|
|
array[6] = v.byte(1);
|
|
array[7] = v.byte(0);
|
|
// user id mask
|
|
array[8] = v.byte(1);
|
|
array[9] = v.byte(0);
|
|
}
|
|
|
|
// memory config mask
|
|
array[10] = config[0];
|
|
array[11] = config[1];
|
|
array[12] = config[16];
|
|
array[13] = config[17];
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::Eeprom) ) {
|
|
// memory eeprom width
|
|
v = data.mask(Pic::MemoryRangeType::Eeprom);
|
|
array[14] = v.byte(1);
|
|
array[15] = v.byte(0);
|
|
// memory eeprom mask
|
|
array[16] = v.byte(1);
|
|
array[17] = v.byte(0);
|
|
}
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::Cal) ) {
|
|
// memory calibration width
|
|
v = data.mask(Pic::MemoryRangeType::Cal);
|
|
array[18] = v.byte(1);
|
|
array[19] = v.byte(0);
|
|
// memory calibration mask
|
|
array[20] = v.byte(1);
|
|
array[21] = v.byte(0);
|
|
}
|
|
|
|
// memory code start
|
|
array[22] = 0x00;
|
|
array[23] = 0x00;
|
|
// memory code length
|
|
array[24] = 0x00; // array[0]; in lplab and for some devices in picp...
|
|
array[25] = 0x01; // array[1]; in lplab and for some devices in picp...
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::UserId) ) {
|
|
// user id start
|
|
v = data.range(Pic::MemoryRangeType::UserId).start.toUInt();
|
|
array[26] = v.byte(1);
|
|
array[27] = v.byte(0);
|
|
// user id length
|
|
v = data.nbWords(Pic::MemoryRangeType::UserId);
|
|
if ( data.nbBytesWord(Pic::MemoryRangeType::UserId)==1 ) v >>= 1;
|
|
array[28] = v.byte(0);
|
|
}
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::Config) ) {
|
|
// config start
|
|
v = data.range(Pic::MemoryRangeType::Config).start.toUInt();
|
|
array[29] = v.byte(1);
|
|
array[30] = v.byte(0);
|
|
// config length
|
|
v = data.nbWords(Pic::MemoryRangeType::Config);
|
|
if ( data.nbBytesWord(Pic::MemoryRangeType::Config)==1 ) v >>= 1;
|
|
array[31] = v.byte(0);
|
|
}
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::Config) ) {
|
|
// eeprom start
|
|
array[32] = 0x00;
|
|
array[33] = 0x00;
|
|
// eeprom length
|
|
v = data.nbWords(Pic::MemoryRangeType::Eeprom);
|
|
array[34] = v.byte(1);
|
|
array[35] = v.byte(0);
|
|
}
|
|
|
|
if ( data.isReadable(Pic::MemoryRangeType::Cal) ) {
|
|
// calibration start
|
|
v = data.range(Pic::MemoryRangeType::Cal).start.toUInt();
|
|
array[36] = v.byte(1);
|
|
array[37] = v.byte(0);
|
|
// calibration length
|
|
v = data.nbWords(Pic::MemoryRangeType::Cal);
|
|
array[38] = v.byte(1);
|
|
array[39] = v.byte(0);
|
|
}
|
|
|
|
// programming
|
|
const Psp::Data &pdata = Psp::data(data.name());
|
|
array[40] = pdata.overprogram;
|
|
array[41] = pdata.tries;
|
|
array[42] = pdata.algorithm;
|
|
if ( data.memoryTechnology()==Device::MemoryTechnology::Flash ) array[43] |= 0x01;
|
|
if ( data.isReadable(Pic::MemoryRangeType::UserId) ) array[43] |= 0x02;
|
|
if ( data.isReadable(Pic::MemoryRangeType::Config) ) array[43] |= 0x04;
|
|
if ( data.isReadable(Pic::MemoryRangeType::Eeprom) ) array[43] |= 0x08;
|
|
if ( data.isReadable(Pic::MemoryRangeType::Cal) ) array[43] |= 0x10;
|
|
if ( data.config().findMask("PARITY") ) array[43] |= 0x20;
|
|
|
|
// checksum
|
|
for (uint i=0; i<44; i++) array[44] += array[i];
|
|
|
|
return array;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Psp::Hardware::Hardware(::Programmer::Base &base, const TQString &portDevice)
|
|
: Programmer::PicHardware(base, new SerialPort(portDevice, base), TQString())
|
|
{}
|
|
|
|
bool Psp::Hardware::internalConnectHardware()
|
|
{
|
|
if ( !port()->open() ) return false;
|
|
if ( !port()->reset() ) return false;
|
|
// #### TODO: detect Warp13 or JuPic
|
|
TQMemArray<uchar> a;
|
|
if ( !port()->command(0x88, 1, a) ) return false;
|
|
if ( a[0]!=0xAB ) {
|
|
log(Log::LineType::Error, i18n("Wrong programmer connected"));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Psp::Hardware::getFirmwareVersion(VersionData &version)
|
|
{
|
|
TQMemArray<uchar> a1;
|
|
if ( !port()->commandAck(0x8D, 2, &a1) ) return false;
|
|
if ( a1[1]==0xFF ) {
|
|
log(Log::LineType::Warning, i18n("Invalid firmware version"));
|
|
version = VersionData(0xFF, 0, 0);
|
|
} else {
|
|
TQMemArray<uchar> a2;
|
|
if ( !port()->receive(2, a2) ) return false;
|
|
version = VersionData(a1[1], a2[0], a2[1]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Psp::Hardware::setTarget()
|
|
{
|
|
log(Log::DebugLevel::Max, "set target");
|
|
// load device info
|
|
if ( !port()->commandAck(0x81) ) return false;
|
|
TQMemArray<uchar> a = createDeviceInfo(device());
|
|
if ( !port()->send(a) ) return false;
|
|
if ( !port()->receiveEnd() ) return false;
|
|
|
|
// load config info
|
|
if ( !port()->commandAck(0x82) ) return false;
|
|
a = createConfigInfo(device());
|
|
if ( !port()->send(a) ) return false;
|
|
if ( !port()->receiveEnd() ) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Psp::Hardware::setRange(uint start, uint size)
|
|
{
|
|
TQMemArray<uchar> a(6);
|
|
a[0] = 0x8E;
|
|
a[1] = start >> 16;
|
|
a[2] = (start >> 8) & 0xFF;
|
|
a[3] = start & 0xFF;
|
|
a[4] = size >> 8;
|
|
a[5] = size & 0xFF;
|
|
if ( !port()->send(a) ) return false;
|
|
TQMemArray<uchar> r;
|
|
if ( !port()->receive(6, r) ) return false;
|
|
for (uint i=0; i<6; i++) {
|
|
if ( r[i]!=a[i] ) {
|
|
log(Log::LineType::Error, i18n("Failed to set range"));
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
char Psp::Hardware::readCommand(Pic::MemoryRangeType type)
|
|
{
|
|
switch (type.type()) {
|
|
case Pic::MemoryRangeType::Code: return 'T';
|
|
case Pic::MemoryRangeType::Eeprom: return 'd';
|
|
case Pic::MemoryRangeType::Config: return 'f';
|
|
case Pic::MemoryRangeType::UserId: return 'e';
|
|
case Pic::MemoryRangeType::Cal: return 'c';
|
|
case Pic::MemoryRangeType::DeviceId:
|
|
case Pic::MemoryRangeType::CalBackup:
|
|
case Pic::MemoryRangeType::DebugVector:
|
|
case Pic::MemoryRangeType::ProgramExecutive:
|
|
case Pic::MemoryRangeType::HardwareStack:
|
|
case Pic::MemoryRangeType::Nb_Types: break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char Psp::Hardware::writeCommand(Pic::MemoryRangeType type)
|
|
{
|
|
switch (type.type()) {
|
|
case Pic::MemoryRangeType::Code: return 'Q';
|
|
case Pic::MemoryRangeType::Eeprom: return 'i';
|
|
case Pic::MemoryRangeType::Config: return 'g';
|
|
case Pic::MemoryRangeType::UserId: return 'h';
|
|
case Pic::MemoryRangeType::Cal: return 'q';
|
|
case Pic::MemoryRangeType::DeviceId:
|
|
case Pic::MemoryRangeType::CalBackup:
|
|
case Pic::MemoryRangeType::DebugVector:
|
|
case Pic::MemoryRangeType::ProgramExecutive:
|
|
case Pic::MemoryRangeType::HardwareStack:
|
|
case Pic::MemoryRangeType::Nb_Types: break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool Psp::Hardware::readMemory(Pic::MemoryRangeType type, Device::Array &data, const ::Programmer::VerifyData *vdata)
|
|
{
|
|
TQMemArray<uchar> a;
|
|
uint nbWords = device().nbWords(type);
|
|
data.resize(nbWords);
|
|
uint nbBytes = nbWords * device().nbBytesWord(type);
|
|
char c = readCommand(type);
|
|
switch (type.type()) {
|
|
case Pic::MemoryRangeType::Code:
|
|
if ( !setRange(0, nbWords) ) return false;
|
|
if ( !port()->commandAck(c) ) return false;
|
|
for (uint i=0; i<data.count(); i++) {
|
|
if ( !port()->receive(2, a) ) return false;
|
|
data[i] = (a[0] << 8) + a[1];
|
|
// log(Log::DebugLevel::Max, TQString("code data %1: %2 (%3, %4)").tqarg(i).tqarg(toHexLabel(data[i], 4))
|
|
// .tqarg(toHexLabel(a[0], 2)).tqarg(toHexLabel(a[1], 2)));
|
|
}
|
|
if ( !port()->receiveEnd() ) return false;
|
|
break;
|
|
case Pic::MemoryRangeType::Eeprom:
|
|
if ( !port()->commandAck(c) ) return false;
|
|
for (uint i=0; i<data.count(); i++) {
|
|
if ( !port()->receive(1, a) ) return false;
|
|
data[i] = a[0];
|
|
}
|
|
if ( !port()->receiveEnd() ) return false;
|
|
break;
|
|
case Pic::MemoryRangeType::UserId:
|
|
if ( !port()->commandAckEnd(c, nbBytes+2, a) ) return false;
|
|
for (uint i=0; i<data.count(); i++) data[i] = (a[1+2*i] << 8) + a[1+2*i+1];
|
|
break;
|
|
case Pic::MemoryRangeType::Config:
|
|
if ( !port()->commandAckEnd(c, nbBytes+2, a) ) return false;
|
|
for (uint i=0; i<data.count(); i++) data[i] = (a[1+2*i] << 8) + a[1+2*i+1];
|
|
break;
|
|
case Pic::MemoryRangeType::Cal:
|
|
if ( !setRange(0, nbWords) ) return false;
|
|
if ( !port()->commandAckEnd(c, nbBytes+2, a) ) return false;
|
|
for (uint i=0; i<data.count(); i++) data[i] = (a[1+2*i] << 8) + a[1+2*i+1];
|
|
break;
|
|
case Pic::MemoryRangeType::DeviceId:
|
|
case Pic::MemoryRangeType::CalBackup:
|
|
data.resize(0);
|
|
return true;
|
|
case Pic::MemoryRangeType::DebugVector:
|
|
case Pic::MemoryRangeType::HardwareStack:
|
|
case Pic::MemoryRangeType::ProgramExecutive:
|
|
case Pic::MemoryRangeType::Nb_Types: Q_ASSERT(false); return false;
|
|
}
|
|
if (vdata) {
|
|
for (uint i=0; i<data.count(); i++)
|
|
if ( !verifyWord(i, data[i], type, *vdata) ) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Psp::Hardware::writeMemory(Pic::MemoryRangeType type, const Device::Array &data, bool force)
|
|
{
|
|
Q_UNUSED(force); // #### TODO: optimize for program memory
|
|
if ( type==Pic::MemoryRangeType::Code && !setRange(0, data.count()) ) return false;
|
|
uint nbBytes = device().nbBytesWord(type);
|
|
if ( !port()->commandAck(writeCommand(type)) ) return false;
|
|
for (uint i=0; i<data.count(); i++)
|
|
if ( !port()->sendData(data[i].toUInt(), nbBytes) ) return false;
|
|
return port()->receiveEnd();
|
|
}
|
|
|
|
bool Psp::Hardware::eraseAll()
|
|
{
|
|
TQMemArray<uchar> a;
|
|
if ( !port()->commandAck(0x8F, 2, &a) ) return false;
|
|
if ( a[1]!=0x00 ) {
|
|
log(Log::LineType::Error, i18n("Erase failed"));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|