/*************************************************************************** * Copyright (C) 2007 Nicolas Hadacek * * * * 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 "pickit2v2.h" #include "progs/base/prog_config.h" #include "progs/icd2/base/microchip.h" #include "pickit2v2_data.h" //----------------------------------------------------------------------------- const Pickit2V2::FamilyData *Pickit2V2::familyData(const Pic::Data &device) { for (uint i=0; FAMILY_DATA[i].architecture!=Pic::Architecture::Nb_Types; i++) if ( FAMILY_DATA[i].architecture==device.architecture() ) return &FAMILY_DATA[i]; Q_ASSERT(false); return 0; } //----------------------------------------------------------------------------- Pickit2V2::Hardware::Hardware(::Programmer::Base &base) : ::Programmer::PicHardware(base, new USBPort(base), TQString()), _scriptBufferChecksum(0), _deviceSet(false) {} bool Pickit2V2::Hardware::internalConnectHardware() { return port().open(); } bool Pickit2V2::Hardware::setTarget() { //setIcspSpeed(0); // #### ?? _fastProgramming = true; // #### ?? uint checksum; if ( !getScriptBufferChecksum(checksum) ) return false; if ( !_deviceSet || _scriptBufferChecksum!=checksum ) { if ( !downloadScripts() ) return false; } _deviceSet = true; return true; } bool Pickit2V2::Hardware::readtqStatus(ushort &status) { if ( !port().command(ReadtqStatus) ) return false; Array a; if ( !port().receive(a) ) return false; status = (a[1] << 8) + a[0]; return true; } bool Pickit2V2::Hardware::sendScript(const ushort *script, uint length) { Array cmd; cmd[0] = ClearUploadBuffer; cmd[1] = ExecuteScript; cmd[2] = length; for (uint i=0; i210 ) vfault = 210; Array cmd; cmd[0] = SetVdd; cmd[1] = v & 0xFF; cmd[2] = v >> 8; cmd[3] = vfault; return port().command(cmd); } bool Pickit2V2::Hardware::setVppVoltage(double value, double threshold) { Array cmd; cmd[0] = SetVpp; cmd[1] = 0x40; cmd[2] = uchar(tqRound(18.61*value)); cmd[3] = uchar(tqRound(18.61*value*threshold)); return port().command(cmd); } bool Pickit2V2::Hardware::setVddOn(bool on) { log(Log::DebugLevel::Extra, TQString("Vdd set to %1, self powered is %2").tqarg(on).tqarg(_base.isTargetSelfPowered())); ushort script[2]; script[0] = (on ? VddGroundOff : VddOff); if ( _base.isTargetSelfPowered() ) script[1] = (on ? VddOff : VddGroundOff); else script[1] = (on ? VddOn : VddGroundOn); return sendScript(script, 2); } bool Pickit2V2::Hardware::setIcspSpeed(uchar speed) { ushort script[2]; script[0] = SetIcspSpeed; script[1] = speed; return sendScript(script, 2); } bool Pickit2V2::Hardware::getMode(VersionData &version, ::Programmer::Mode &mode) { if ( !port().command(FirmwareVersion) ) return false; Array data; if ( !port().receive(data) ) return false; if ( data[0]=='B' ) { mode = ::Programmer::BootloadMode; version = VersionData(); } else { mode = ::Programmer::NormalMode; version = VersionData(data[0], data[1], data[2]); } return true; } bool Pickit2V2::Hardware::readVoltages(VoltagesData &voltagesData) { if ( !port().command(ReadVoltages) ) return false; Array array; if ( !port().receive(array) ) return false; double vadc = 256 * array[1] + array[0]; voltagesData[Pic::TargetVdd].value = 5.0 * (vadc / 65536); voltagesData[Pic::TargetVdd].error = false; vadc = 256 * array[3] + array[2]; voltagesData[Pic::TargetVpp].value = 13.7 * (vadc / 65536); voltagesData[Pic::TargetVpp].error = false; return true; } bool Pickit2V2::Hardware::downloadAddress(Address address) { log(Log::DebugLevel::Max, TQString("download address %1").tqarg(toHexLabel(address, 6))); Array cmd; cmd[0] = ClearDownloadBuffer; cmd[1] = DownloadData; cmd[2] = 3; cmd[3] = address.toUInt() & 0xFF; cmd[4] = (address.toUInt() >> 8) & 0xFF; cmd[5] = (address.toUInt() >> 16) & 0xFF; return port().command(cmd); } bool Pickit2V2::Hardware::runScript(ScriptType stype, uint repetitions, uint nbNoLens) { log(Log::DebugLevel::Max, TQString("run script %1: repetitions=%2 nbNoLen=%3") .tqarg(toHexLabel(stype, 2)).tqarg(repetitions).tqarg(nbNoLens)); #if 0 // ALTERNATE METHOD const Data &d = data(device().name()); for (uint i=0; i words; if ( type==Pic::MemoryRangeType::Config || type==Pic::MemoryRangeType::Cal ) { if ( !runScript(stype, 1, 0) ) return false; if ( !port().command(UploadData) ) return false; // config memory return includes a length byte that we need to ignore if ( !port().receiveWords(nbBytesWord, nbReceive, words, 1) ) return false; } else { if ( !runScript(stype, nbRuns, nbReceive) ) return false; if ( !port().receiveWords(nbBytesWord, nbReceive, words) ) return false; } log(Log::DebugLevel::Max, TQString("nbRunWords=%1 readNbWords=%2 index=%3/%4").tqarg(nbRunWords).tqarg(words.count()).tqarg(i).tqarg(nbWords)); for (uint k=0; k=nbWords ) break; data[i] = words[k]; if (fdata->progMemShift) data[i] >>= 1; data[i] = data[i].maskWith(device().mask(type)); // ### correct ? if ( vdata && !verifyWord(i, data[i], type, *vdata) ) return false; if ( type==Pic::MemoryRangeType::Code && i!=0x0 && i%0x8000==0 ) setAddress = true; i++; } } if ( !runScript(ProgExit) ) return false; return true; } bool Pickit2V2::Hardware::eraseAll() { const Data &d = data(device().name()); if ( d.scriptIndexes[ConfigErase]!=0 ) { if ( !runScript(ProgEntry) ) return false; if ( d.scriptIndexes[ConfigWritePrepare]!=0 ) { if ( !downloadAddress(0) ) return false; if ( !runScript(ConfigWritePrepare) ) return false; } if ( !runScript(ConfigErase) ) return false; if ( !runScript(ProgExit) ) return false; } if ( !runScript(ProgEntry) ) return false; if ( d.scriptIndexes[EraseChipPrepare]!=0 && !runScript(EraseChipPrepare) ) return false; if ( !runScript(ChipErase) ) return false; if ( !runScript(ProgExit) ) return false; return true; } bool Pickit2V2::Hardware::eraseRange(Pic::MemoryRangeType type) { if ( type==Pic::MemoryRangeType::Code ) { if ( !runScript(ProgEntry) ) return false; if ( !runScript(ProgMemoryErase) ) return false; if ( !runScript(ProgExit) ) return false; return true; } if ( type==Pic::MemoryRangeType::Eeprom ) { if ( !runScript(ProgEntry) ) return false; if ( !runScript(EepromErase) ) return false; if ( !runScript(ProgExit) ) return false; return true; } Q_ASSERT(false); return false; } bool Pickit2V2::Hardware::prepareWrite(Pic::MemoryRangeType type, uint wordIndex) { ScriptType stype = prepareWriteScript(type); if ( stype==Nb_ScriptTypes || data(device().name()).scriptIndexes[stype]==0 ) return true; switch (type.type()) { case Pic::MemoryRangeType::Code: case Pic::MemoryRangeType::Config: if ( !device().architecture().data().hasAddressAccess ) return true; if ( !downloadAddress(0x10000 * (wordIndex / 0x8000)) ) return false; break; case Pic::MemoryRangeType::Eeprom: { Address address = (device().nbBytesWord(Pic::MemoryRangeType::Eeprom)==4 ? device().range(Pic::MemoryRangeType::Eeprom).start : 0x000000); if ( !downloadAddress(address) ) return false; break; } case Pic::MemoryRangeType::UserId: break; default: return true; case Pic::MemoryRangeType::Nb_Types: Q_ASSERT(false); return false; } return runScript(stype); } bool Pickit2V2::Hardware::writeMemory(Pic::MemoryRangeType otype, const Device::Array &data, bool force) { Q_UNUSED(force); return false; // ### TODO } //----------------------------------------------------------------------------- bool Pickit2V2::DeviceSpecific::canEraseRange(Pic::MemoryRangeType type) const { const Data &d = data(device().name()); if ( type==Pic::MemoryRangeType::Code ) return d.scriptIndexes[ProgMemoryErase]; if ( type==Pic::MemoryRangeType::Eeprom ) return d.scriptIndexes[EepromErase]; return false; } bool Pickit2V2::DeviceSpecific::canReadRange(Pic::MemoryRangeType type) const { const Data &d = data(device().name()); if ( type==Pic::MemoryRangeType::Cal ) return d.scriptIndexes[OsccalRead]; return true; } bool Pickit2V2::DeviceSpecific::canWriteRange(Pic::MemoryRangeType type) const { const Data &d = data(device().name()); if ( type==Pic::MemoryRangeType::Cal ) return d.scriptIndexes[OsccalWrite]; return true; } bool Pickit2V2::DeviceSpecific::doWrite(Pic::MemoryRangeType type, const Device::Array &data, bool force) { Q_ASSERT( data.size()==device().nbWords(type) ); return hardware().writeMemory(type, data, force); }