/*************************************************************************** * Copyright (C) 2006 Nicolas Hadacek * * Copyright (C) 2002-2003 Stephen Landamore * * * * 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 Psp::createConfigInfo(const Pic::Data &data) { TQMemArray array(33); array.fill(0x00); const Pic::Config &config = data.config(); for (uint i=0; i Psp::createDeviceInfo(const Pic::Data &data) { TQMemArray config = createConfigInfo(data); TQMemArray 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 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 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 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 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 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 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 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; ireceive(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; ireceive(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; icommandAckEnd(c, nbBytes+2, a) ) return false; for (uint i=0; icommandAckEnd(c, nbBytes+2, a) ) return false; for (uint i=0; icommandAck(writeCommand(type)) ) return false; for (uint i=0; isendData(data[i].toUInt(), nbBytes) ) return false; return port()->receiveEnd(); } bool Psp::Hardware::eraseAll() { TQMemArray a; if ( !port()->commandAck(0x8F, 2, &a) ) return false; if ( a[1]!=0x00 ) { log(Log::LineType::Error, i18n("Erase failed")); return false; } return true; }