summaryrefslogtreecommitdiffstats
path: root/src/progs/icd2/base/icd2_debug_specific.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/progs/icd2/base/icd2_debug_specific.cpp')
-rw-r--r--src/progs/icd2/base/icd2_debug_specific.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/progs/icd2/base/icd2_debug_specific.cpp b/src/progs/icd2/base/icd2_debug_specific.cpp
new file mode 100644
index 0000000..56cc178
--- /dev/null
+++ b/src/progs/icd2/base/icd2_debug_specific.cpp
@@ -0,0 +1,255 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * 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 "icd2_debug_specific.h"
+
+#include "devices/pic/base/pic_register.h"
+#include "icd2_data.h"
+
+//----------------------------------------------------------------------------
+Address Icd2::P16FDebuggerSpecific::addressWREG() const
+{
+ return FAMILY_DATA[family(device()->name())].wreg;
+}
+
+Address Icd2::P16FDebuggerSpecific::addressRegister(Address address) const
+{
+ QString name = device()->registersData().sfrNames[address];
+ if ( name=="FSR" ) return FAMILY_DATA[family(device()->name())].fsr;
+ if ( name=="STATUS" ) return FAMILY_DATA[family(device()->name())].status;
+ return address;
+}
+
+bool Icd2::P16FDebuggerSpecific::reset()
+{
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ return init(true);
+}
+
+bool Icd2::P16FDebuggerSpecific::setBreakpoint(Address address)
+{
+ if ( !address.isValid() ) address = 0x1FFF; // outside memory range
+ BitValue value = address.toUInt() | 0x8000; // read-only INBUG bit
+ return hardware()->writeRegister(0x18E, value, 2);
+}
+
+bool Icd2::P16FDebuggerSpecific::readBreakpoint(BitValue &value)
+{
+ if ( !hardware()->readRegister(0x18E, value, 2) ) return false;
+ value = value.maskWith(0x1FFF);
+ return true;
+}
+
+bool Icd2::P16FDebuggerSpecific::beginInit(Device::Array *saved)
+{
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ double vdd;
+ if ( !hardware()->readVoltage(Pic::TargetVdd, vdd) ) return false;
+ log(Log::DebugLevel::Normal, QString(" Target Vdd: %1 V").arg(vdd));
+
+ if (saved) {
+ saved->resize(1);
+ if ( !hardware()->readMemory(Pic::MemoryRangeType::Code, 0, *saved, 0) ) return false; // save first instruction
+ if ( (*saved)[0]!=device()->nopInstruction() ) log(Log::LineType::Warning, i18n(" According to ICD2 manual, instruction at address 0x0 should be \"nop\"."));
+ }
+
+ return true;
+}
+
+bool Icd2::P16FDebuggerSpecific::endInit(BitValue expectedPC)
+{
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetStopped) ) return false;
+ BitValue value;
+ if ( !readBreakpoint(value) ) return false;
+ if ( value==expectedPC+1 ) {
+ // #### happen for some custom icd2 or sometimes when we had to force a halt (?)
+ expectedPC = expectedPC+1;
+ //log(Log::LineType::Information, i18n("Detected custom ICD2"));
+ }
+ if ( value!=expectedPC ) {
+ log(Log::LineType::Error, i18n(" PC is not at address %1 (%2)").arg(toHexLabel(expectedPC, 4)).arg(toHexLabel(value, 4)));
+ return false;
+ }
+ if ( !setBreakpoint(0x0000) ) return false;
+
+ if ( !base().update() ) return false;
+ if ( base().pc()!=expectedPC ) {
+ log(Log::LineType::Error, i18n(" PC is not at address %1 (%2)").arg(toHexLabel(expectedPC, 4)).arg(toHexLabel(base().pc(), 4)));
+ return false;
+ }
+ return true;
+}
+
+bool Icd2::P16F872DebuggerSpecific::init(bool)
+{
+ Device::Array saved;
+ if ( !beginInit(&saved) ) return false;
+
+ // this seems to be needed
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false;
+ Pic::TargetMode mode;
+ if ( !programmer().getTargetMode(mode) ) return false;
+
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ if ( !hardware()->setWriteMode(Pic::EraseWriteMode) ) return false;
+ log(Log::DebugLevel::Normal, " Write \"goto 0x0\" at reset vector and run target.");
+ Device::Array data = device()->gotoInstruction(0x0000, false); // loop at reset vector
+ if ( !hardware()->writeMemory(Pic::MemoryRangeType::Code, 0, data) ) return false;
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false; // run device
+ if ( !base().waitForTargetMode(Pic::TargetRunning) ) return false;
+ log(Log::DebugLevel::Normal, " Try to halt target.");
+ if ( !hardware()->haltRun() ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetStopped) ) return false;
+ if ( !programmer().readDebugExecutiveVersion() ) return false;
+ log(Log::DebugLevel::Normal, " Set breakpoint at reset vector.");
+ if ( !setBreakpoint(0x0000) ) return false;
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetInProgramming) ) return false;
+ log(Log::DebugLevel::Normal, " Restore instruction at reset vector and run target.");
+ if ( !hardware()->writeMemory(Pic::MemoryRangeType::Code, 0, saved) ) return false; // restore instruction
+ if ( !hardware()->setWriteMode(Pic::WriteOnlyMode) ) return false;
+
+ return endInit(0x0001);
+}
+
+bool Icd2::P16F87XDebuggerSpecific::init(bool)
+{
+ Device::Array saved;
+ if ( !beginInit(&saved) ) return false;
+
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ if ( !hardware()->setWriteMode(Pic::EraseWriteMode) ) return false;
+ log(Log::DebugLevel::Normal, " Write \"goto 0x0\" at reset vector and run target.");
+ Device::Array data = device()->gotoInstruction(0x0000, false); // loop at reset vector
+ if ( !hardware()->writeMemory(Pic::MemoryRangeType::Code, 0, data) ) return false;
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false; // run device
+ Pic::TargetMode mode;
+ if ( !programmer().getTargetMode(mode) ) return false;
+ if ( mode==Pic::TargetRunning && !hardware()->haltRun() ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetStopped) ) return false;
+ if ( !programmer().readDebugExecutiveVersion() ) return false;
+ log(Log::DebugLevel::Normal, " Set breakpoint at reset vector.");
+ if ( !setBreakpoint(0x0000) ) return false;
+ if ( !hardware()->setTargetReset(Pic::ResetHeld) ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetInProgramming) ) return false;
+ log(Log::DebugLevel::Normal, " Restore instruction at reset vector and run target.");
+ if ( !hardware()->writeMemory(Pic::MemoryRangeType::Code, 0, saved) ) return false; // restore instruction
+ if ( !hardware()->setWriteMode(Pic::WriteOnlyMode) ) return false;
+
+ return endInit(0x0001);
+}
+
+bool Icd2::P16F7X7DebuggerSpecific::init(bool last)
+{
+ Device::Array saved;
+ if ( !beginInit(last ? &saved : 0) ) return false;
+
+ log(Log::DebugLevel::Normal, " Run target.");
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetStopped) ) return false;
+ if ( !programmer().readDebugExecutiveVersion() ) return false;
+
+ BitValue value;
+ if ( !readBreakpoint(value) ) return false;
+ BitValue expectedPC = (last ? 0x0001 : 0x0000);
+ if ( value==expectedPC+1 ) {
+ expectedPC = expectedPC+1;
+ log(Log::DebugLevel::Normal, "Probably detected custom ICD2");
+ }
+ if ( value!=expectedPC )
+ log(Log::DebugLevel::Normal, i18n(" PC is not at address %1 (%2)").arg(toHexLabel(expectedPC, 4)).arg(toHexLabel(value, 4)));
+ if ( !setBreakpoint(0x0000) ) return false;
+
+ if ( !base().update() ) return false;
+ // #### not sure if there is a better way to get initial values (we are stopped here...)
+ Register::list().setValue(base().pcTypeData(), value);
+ Register::list().setValue(base().registerTypeData("STATUS"), 0x0);
+ Register::list().setValue(deviceSpecific()->wregTypeData(), 0x0);
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+Icd2::P18FDebuggerSpecific::P18FDebuggerSpecific(::Debugger::Base &base)
+ : DebuggerSpecific(base)
+{
+ const Pic::RegistersData &rdata = device()->registersData();
+ // find last used bank (but not #15)
+ _reservedBank = rdata.nbBanks - 1; // #14
+ for (uint i=1; i<rdata.nbBanks-1; i++) {
+ if ( rdata.isBankUsed(i) ) continue;
+ _reservedBank = i - 1;
+ break;
+ }
+ // check it's not a bank for CAN
+ for (; _reservedBank>0; _reservedBank--)
+ if ( !rdata.bankHasSfrs(_reservedBank) ) break;
+ // also take care of USB RAM
+ if ( (device()->architecture()==Pic::Architecture::P18F || device()->architecture()==Pic::Architecture::P18J)
+ && device()->hasFeature(Pic::Feature::USB) ) {
+ if ( _reservedBank==7 ) _reservedBank = 3; // 18F2455 family: 4 USB RAM banks
+ // 18F87J50 family ?
+ }
+}
+
+Address Icd2::P18FDebuggerSpecific::addressWREG()const
+{
+ return reservedRegisterOffset() | 0x0FF;
+}
+
+Address Icd2::P18FDebuggerSpecific::addressRegister(Address address) const
+{
+ QString name = device()->registersData().sfrNames[address];
+ if ( name=="PCLATU" ) return reservedRegisterOffset() | 0x0F4;
+ if ( name=="PCLATH" ) return reservedRegisterOffset() | 0x0F5;
+ if ( name=="FSR0H" ) return reservedRegisterOffset() | 0x0FB;
+ if ( name=="FSR0L" ) return reservedRegisterOffset() | 0x0FC;
+ if ( name=="BSR" ) return reservedRegisterOffset() | 0x0FD;
+ if ( name=="STATUS" ) return reservedRegisterOffset() | 0x0FE;
+ return address;
+}
+
+bool Icd2::P18FDebuggerSpecific::setBreakpoint(Address address)
+{
+ BitValue value = (address.isValid() ? address.toUInt() << 15 : 0x0FFFFF00); // ??
+ return hardware()->writeRegister(0xFB6, value, 4);
+}
+
+bool Icd2::P18FDebuggerSpecific::readBreakpoint(BitValue &value)
+{
+ if ( !hardware()->readRegister(0xFB6, value, 4) ) return false;
+ value >>= 15;
+ return true;
+}
+
+bool Icd2::P18FDebuggerSpecific::reset()
+{
+ if ( !hardware()->writeRegister(0xFB5, 0x00, 1) ) return false; // #### ??
+ if ( !hardware()->writeRegister(0xFB5, 0x01, 1) ) return false; // #### ??
+ if ( !hardware()->command("2D", 0) ) return false; // reset
+ if ( !hardware()->writeRegister(0xFB5, 0x00, 1) ) return false; // #### ??
+ if ( !base().update() ) return false;
+ BitValue expectedPC = 0x0000;
+ if ( base().pc()==0x0001) {
+ expectedPC = 0x0001;
+ log(Log::LineType::Information, i18n("Detected custom ICD2"));
+ }
+ if ( base().pc()!=expectedPC ) {
+ log(Log::LineType::Error, i18n(" PC is not at address %1 (%2)").arg(toHexLabel(expectedPC, 4)).arg(toHexLabel(base().pc(), 4)));
+ return false;
+ }
+ return true;
+}
+
+bool Icd2::P18FDebuggerSpecific::init(bool)
+{
+ if ( !hardware()->setTargetReset(Pic::ResetReleased) ) return false;
+ if ( !base().waitForTargetMode(Pic::TargetStopped) ) return false;
+ return reset();
+}