summaryrefslogtreecommitdiffstats
path: root/src/devices/pic/base
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
commitf508189682b6fba62e08feeb1596f682bad5fff9 (patch)
tree28aeb0e6c19386c385c1ce5edf8a92c1bca15281 /src/devices/pic/base
downloadpiklab-f508189682b6fba62e08feeb1596f682bad5fff9.tar.gz
piklab-f508189682b6fba62e08feeb1596f682bad5fff9.zip
Added KDE3 version of PikLab
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/piklab@1095639 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/devices/pic/base')
-rw-r--r--src/devices/pic/base/Makefile.am6
-rw-r--r--src/devices/pic/base/base.pro6
-rw-r--r--src/devices/pic/base/pic.cpp426
-rw-r--r--src/devices/pic/base/pic.h179
-rw-r--r--src/devices/pic/base/pic_config.cpp456
-rw-r--r--src/devices/pic/base/pic_config.h107
-rw-r--r--src/devices/pic/base/pic_protection.cpp361
-rw-r--r--src/devices/pic/base/pic_protection.h60
-rw-r--r--src/devices/pic/base/pic_register.cpp287
-rw-r--r--src/devices/pic/base/pic_register.h115
10 files changed, 2003 insertions, 0 deletions
diff --git a/src/devices/pic/base/Makefile.am b/src/devices/pic/base/Makefile.am
new file mode 100644
index 0000000..ebade1c
--- /dev/null
+++ b/src/devices/pic/base/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libpicbase.la
+libpicbase_la_SOURCES = pic.cpp pic_config.cpp pic_protection.cpp \
+ pic_register.cpp
diff --git a/src/devices/pic/base/base.pro b/src/devices/pic/base/base.pro
new file mode 100644
index 0000000..621d6d3
--- /dev/null
+++ b/src/devices/pic/base/base.pro
@@ -0,0 +1,6 @@
+STOPDIR = ../../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = picbase
+HEADERS += pic_protection.h pic_config.h pic_register.h pic.h
+SOURCES += pic_protection.cpp pic_config.cpp pic_register.cpp pic.cpp
diff --git a/src/devices/pic/base/pic.cpp b/src/devices/pic/base/pic.cpp
new file mode 100644
index 0000000..8f81540
--- /dev/null
+++ b/src/devices/pic/base/pic.cpp
@@ -0,0 +1,426 @@
+/***************************************************************************
+ * Copyright (C) 2005 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 "pic.h"
+
+#include "common/global/global.h"
+#include "common/common/misc.h"
+#include "common/global/purl.h"
+#include "pic_register.h"
+#include "pic_config.h"
+
+//------------------------------------------------------------------------------
+const Pic::ProgVoltageType::Data Pic::ProgVoltageType::DATA[Nb_Types] = {
+ { "vpp", 0 },
+ { "vdd_prog", 0 },
+ { "vdd_prog_write", 0 }
+};
+
+const Pic::MemoryRangeType::Data Pic::MemoryRangeType::DATA[Nb_Types] = {
+ { "code", I18N_NOOP("Code memory"), Writable },
+ { "calibration", I18N_NOOP("Calibration"), Writable },
+ { "user_ids", I18N_NOOP("User IDs"), Writable },
+ { "device_id", I18N_NOOP("Device ID"), ReadOnly },
+ { "config", I18N_NOOP("Configuration Bits"), Writable },
+ { "eeprom", I18N_NOOP("Data EEPROM"), Writable },
+ { "debug_vector", I18N_NOOP("Debug Vector"), Writable },
+ { "hardware_stack", I18N_NOOP("Hardware Stack"), ReadOnly },
+ { "calibration_backup", I18N_NOOP("Calibration Backup"), Writable },
+ { "program_executive", I18N_NOOP("Program Executive"), Writable }
+};
+
+const Pic::SelfWrite::Data Pic::SelfWrite::DATA[Nb_Types] = {
+ { "yes", 0 },
+ { "no", 0 }
+};
+
+const Pic::DeviceType::Data Pic::DeviceType::DATA[Nb_Types] = {
+ { 0, I18N_NOOP("Normal") },
+ { 0, I18N_NOOP("J") },
+ { 0, I18N_NOOP("K") }
+};
+
+const Pic::Architecture::Data Pic::Architecture::DATA[Nb_Types] = {
+// name family_label nbBytesPC nbBytesWord packed nbBitsRegister registerBankLength
+// {Code, Cal, UserID, DevId, Conf, EEPROM, DebugVec, HardStack, CalBackup, Program Executive} randomAccess
+ { "10X", I18N_NOOP("Baseline Family"), 0, 2, false, 8, 0x020, { 12, 12, 12, 12, 12, 8, 12, 0, 12, 0 }, false, SelfWrite::No, DeviceType::Normal }, // 9, 10, 11 or 12-bit program counter
+ { "16X", I18N_NOOP("Midrange Family"), 13, 2, false, 8, 0x080, { 14, 14, 14, 14, 14, 8, 14, 0, 14, 0 }, false, SelfWrite::Nb_Types, DeviceType::Normal }, // max eeprom: 256 words
+ { "17C", I18N_NOOP("17C Family"), 16, 2, false, 8, 0x100, { 16, 0, 0, 0, 16, 8, 0, 0, 0, 0 }, true, SelfWrite::No, DeviceType::Normal },
+ { "18C", I18N_NOOP("18C Family"), 21, 2, true, 8, 0x100, { 16, 8, 8, 8, 8, 8, 16, 0, 8, 0 }, true, SelfWrite::No, DeviceType::Normal },
+ { "18F", I18N_NOOP("18F Family"), 21, 2, true, 8, 0x100, { 16, 8, 8, 8, 8, 8, 16, 0, 8, 0 }, true, SelfWrite::Nb_Types, DeviceType::Normal },
+ { "18J", I18N_NOOP("18J Family"), 21, 2, true, 8, 0x100, { 16, 8, 8, 8, 8, 8, 16, 0, 8, 0 }, true, SelfWrite::Yes, DeviceType::J },
+ { "24F", I18N_NOOP("24F Family"), 23, 4, false, 16, 0x800, { 24, 0, 0, 16, 24, 0, 24, 0, 0, 24 }, true, SelfWrite::Yes, DeviceType::J },
+ { "24H", I18N_NOOP("24H Family"), 23, 4, false, 16, 0x800, { 24, 0, 8, 16, 8, 0, 24, 0, 0, 24 }, true, SelfWrite::Yes, DeviceType::J },
+ { "30F", I18N_NOOP("30F Family"), 23, 4, false, 16, 0xA00, { 24, 0, 24, 16, 16, 16, 24, 0, 0, 24 }, true, SelfWrite::Yes, DeviceType::Normal }, // dsPIC: eeprom max = 2 kwords = 4 kbytes
+ { "33F", I18N_NOOP("33F Family"), 23, 4, false, 16, 0x800, { 24, 0, 8, 16, 8, 0, 24, 0, 0, 24 }, true, SelfWrite::Yes, DeviceType::J }
+};
+
+const Pic::Checksum::Algorithm::Data Pic::Checksum::Algorithm::DATA[Nb_Types] = {
+ { "", 0 },
+ { "XOR4", 0 },
+ { "XNOR7", 0 },
+ { "XNOR8", 0 }
+};
+
+const Pic::Feature::Data Pic::Feature::DATA[Nb_Types] = {
+ { "ccp", I18N_NOOP("CCP") },
+ { "adc", I18N_NOOP("ADC") },
+ { "ssp", I18N_NOOP("SSP") },
+ { "lvd", I18N_NOOP("Low Voltage Detect") },
+ { "usb", I18N_NOOP("USB") },
+ { "usart", I18N_NOOP("USART") },
+ { "can", I18N_NOOP("CAN") },
+ { "ecan", I18N_NOOP("ECAN") },
+ { "ethernet", I18N_NOOP("Ethernet") },
+ { "lcd", I18N_NOOP("LCD") },
+ { "motor_control", I18N_NOOP("Motor Control") },
+ { "motion_feedback", I18N_NOOP("Motion Feeback") },
+ { "self_write", I18N_NOOP("Self-Write") }
+};
+
+//-----------------------------------------------------------------------------
+Pic::Data::Data()
+ : Device::Data(new RegistersData(*this))
+{
+ FOR_EACH(ProgVoltageType, type) {
+ _voltages[type].min = 0.0;
+ _voltages[type].max = 0.0;
+ _voltages[type].nominal = 0.0;
+ }
+ FOR_EACH(MemoryRangeType, type) {
+ _ranges[type].properties = NotPresent;
+ _ranges[type].start = 0;
+ _ranges[type].end = 0;
+ _ranges[type].hexFileOffset = 0;
+ }
+ _config = new Config(*this);
+ _calibration.opcode = 0;
+ _calibration.opcodeMask = 0;
+}
+
+Pic::Data::~Data()
+{
+ delete _config;
+}
+
+bool Pic::Data::isReadable(MemoryRangeType type) const
+{
+ return ( range(type).properties & Programmable );
+}
+
+bool Pic::Data::isWritable(MemoryRangeType type) const
+{
+ return ( (type.data().properties & Writable) && (range(type).properties & Programmable) );
+}
+
+uint Pic::Data::addressIncrement(MemoryRangeType type) const
+{
+ uint inc = _architecture.data().nbBytesWord;
+ if ( _architecture.data().packed
+ && ( type==MemoryRangeType::Code || type==MemoryRangeType::DebugVector ) ) return inc;
+ return inc / 2;
+}
+
+uint Pic::Data::nbWords(MemoryRangeType type) const
+{
+ if ( !isPresent(type) ) return 0;
+ return nbAddresses(type) / addressIncrement(type);
+}
+
+uint Pic::Data::nbAddresses(MemoryRangeType type) const
+{
+ if ( !isPresent(type) ) return 0;
+ return (range(type).end - range(type).start + 1);
+}
+
+QString Pic::Data::fname(Device::Special special) const
+{
+ QString s = name();
+ switch (special.type()) {
+ case Device::Special::Normal: break;
+ case Device::Special::LowPower:
+ // assume name is of form "NNX..."
+ s.insert(2, 'L');
+ break;
+ case Device::Special::LowVoltage:
+ // assume name is of form "NNXN..."
+ s.replace(2, 1, "LV");
+ break;
+ case Device::Special::HighVoltage:
+ // assume name is of form "NNXN..."
+ s.replace(2, 1, "HV");
+ break;
+ case Device::Special::Nb_Types: Q_ASSERT(false); break;
+ }
+ return s;
+}
+
+bool Pic::Data::matchId(BitValue rawId, Device::IdData &idata) const
+{
+ if ( !isPresent(MemoryRangeType::DeviceId) ) return false;
+ QMap<Device::Special, BitValue>::const_iterator it;
+ for (it=_ids.begin(); it!=_ids.end(); ++it) {
+ idata.special = it.key();
+ BitValue nid = 0x0;
+ switch (architecture().type()) {
+ case Architecture::P10X:
+ case Architecture::P16X:
+ case Architecture::P17C:
+ case Architecture::P18C:
+ case Architecture::P18F:
+ case Architecture::P18J:
+ nid = rawId.clearMaskBits(0x1F);
+ idata.revision = rawId.maskWith(0x1F);
+ break;
+ case Architecture::P24F:
+ nid = (rawId >> 16).maskWith(0x3FFF);
+ idata.revision = (rawId >> 6).maskWith(0x7);
+ idata.minorRevision = rawId.maskWith(0x7);
+ break;
+ case Architecture::P30F:
+ nid = (rawId >> 16).maskWith(0xFFFF);
+ idata.revision = (rawId >> 6).maskWith(0x3F);
+ idata.minorRevision = rawId.maskWith(0x3F);
+ idata.process = (rawId >> 12).maskWith(0xF);
+ break;
+ case Architecture::P24H:
+ case Architecture::P33F:
+ nid = (rawId >> 16).maskWith(0xFFFF);
+ idata.revision = rawId.maskWith(0xFFFF); // ??
+ break;
+ case Architecture::Nb_Types: Q_ASSERT(false); break;
+ }
+ if ( nid==it.data() ) return true;
+ }
+ return false;
+}
+
+QStringList Pic::Data::idNames(const QMap<QString, Device::IdData> &ids) const
+{
+ QStringList list;
+ QMap<QString, Device::IdData>::const_iterator it;
+ for (it=ids.begin(); it!=ids.end(); ++it) {
+ switch (_architecture.type()) {
+ case Architecture::P10X:
+ case Architecture::P16X:
+ case Architecture::P17C:
+ case Architecture::P18C:
+ case Architecture::P18F:
+ case Architecture::P18J:
+ list += i18n("%1 (rev. %2)").arg(it.key()).arg(toLabel(it.data().revision));
+ break;
+ case Architecture::P24F:
+ list += i18n("%1 (rev. %2.%3)").arg(it.key()).arg(toLabel(it.data().revision)).arg(toLabel(it.data().minorRevision));
+ break;
+ case Architecture::P30F:
+ list += i18n("%1 (proc. %2; rev. %3.%4)").arg(it.key()).arg(toLabel(it.data().process)).arg(toLabel(it.data().revision)).arg(toLabel(it.data().minorRevision));
+ break;
+ case Architecture::P24H:
+ case Architecture::P33F:
+ list += i18n("%1 (rev. %2)").arg(it.key()).arg(toLabel(it.data().revision));
+ break;
+ case Architecture::Nb_Types: Q_ASSERT(false); break;
+ }
+ }
+ return list;
+}
+
+bool Pic::Data::checkCalibration(const Device::Array &data, QString *message) const
+{
+ Q_ASSERT( nbWords(MemoryRangeType::Cal)==data.count() );
+ for (uint i=0; i<data.count(); i++) {
+ QString address = toHexLabel(range(MemoryRangeType::Cal).start + i*addressIncrement(MemoryRangeType::Cal), nbCharsAddress());
+ if ( data[i]==mask(MemoryRangeType::Cal) ) {
+ if (message) *message = i18n("Calibration word at address %1 is blank.").arg(address);
+ return false;
+ }
+ }
+ if ( data.count()==1 ) {
+ if ( data[0].maskWith(_calibration.opcodeMask)!=_calibration.opcode ) {
+ if (message) *message = i18n("Calibration word is not a compatible opcode (%2).")
+ .arg(toHexLabel(_calibration.opcode, nbCharsWord(MemoryRangeType::Code)));
+ return false;
+ }
+ }
+ return true;
+}
+
+const Pic::RegistersData &Pic::Data::registersData() const
+{
+ return static_cast<const RegistersData &>(*_registersData);
+}
+
+bool Pic::Data::hasFeature(Feature feature, bool *unknown) const
+{
+ bool ok = ( registersData().nbBanks!=0 );
+ if (unknown) *unknown = !ok;
+ if (!ok) return false;
+ switch (feature.type()) {
+ case Feature::CCP: return registersData().sfrs.contains("CCP1CON");
+ case Feature::ADC: return registersData().sfrs.contains("ADCON0");
+ case Feature::SSP: return registersData().sfrs.contains("SSPCON");
+ case Feature::LVD: return registersData().sfrs.contains("LVDCON");
+ case Feature::USB: return registersData().sfrs.contains("UCON");
+ case Feature::USART:
+ return ( registersData().sfrs.contains("TXSTA") // 16F
+ || registersData().sfrs.contains("TXSTA1") // 18F
+ || registersData().sfrs.contains("U1MODE") ); // 30F
+ case Feature::CAN: return registersData().sfrs.contains("CANCON") && !registersData().sfrs.contains("ECANCON");
+ case Feature::ECAN: return registersData().sfrs.contains("ECANCON");
+ case Feature::Ethernet: return registersData().sfrs.contains("ETHCON1");
+ case Feature::LCD: return registersData().sfrs.contains("LCDCON");
+ case Feature::MotorControl: return registersData().sfrs.contains("PWMCON0");
+ case Feature::MotionFeedback: return registersData().sfrs.contains("CAP1CON");
+ case Feature::SelfWrite: return _selfWrite==SelfWrite::Yes;
+ case Feature::Nb_Types: Q_ASSERT(false); break;
+ }
+ return false;
+}
+
+Device::Array Pic::Data::gotoInstruction(Address address, bool withPageSelection) const
+{
+ Q_ASSERT( address<addressIncrement(MemoryRangeType::Code)*nbWords(MemoryRangeType::Code) );
+ Device::Array a;
+ switch (_architecture.type()) {
+ case Architecture::P10X:
+ if ( nbWords(MemoryRangeType::Code)>0x1FF && withPageSelection)
+ a.append(0x4A3 | (address>0x1FF ? 0x100 : 0x000)); // bsf STATUS,PA0 or bcf STATUS,PA0
+ a.append(0xA00 | (address.toUInt() & 0x1FF)); // goto
+ break;
+ case Architecture::P16X:
+ if ( nbWords(MemoryRangeType::Code)>0x7FF && withPageSelection ) {
+ if ( address<=0x7FF ) a.append(0x018A); // clrf PCLATH
+ else {
+ a.append(0x3000 | (address.toUInt() >> 8)); // movl high address
+ a.append(0x008A); // movwf PCLATH
+ }
+ }
+ a.append(0x2800 | (address.toUInt() & 0x7FF));
+ break;
+ case Architecture::P17C:
+ a.append(0xC000 | (address.toUInt() & 0x1FFF));
+ break;
+ case Architecture::P18C:
+ case Architecture::P18F:
+ case Architecture::P18J:
+ a.append(0xEF00 | ((address.toUInt()/2) & 0xFF));
+ a.append(0xF000 | ((address.toUInt()/2) >> 8));
+ break;
+ case Architecture::P24F:
+ case Architecture::P24H:
+ case Architecture::P30F:
+ case Architecture::P33F:
+ a.append(0x040000 | (address.toUInt() & 0x00FFFE));
+ a.append(0X000000 | (address.toUInt() >> 16));
+ break;
+ case Architecture::Nb_Types: Q_ASSERT(false); break;
+ }
+ return a;
+}
+
+bool Pic::Data::isGotoInstruction(BitValue instruction) const
+{
+ switch (_architecture.type()) {
+ case Architecture::P10X: return ( instruction.maskWith(0xE00)==0xA00 );
+ case Architecture::P16X: return ( instruction.maskWith(0xF800)==0x2800 );
+ case Architecture::P17C: return ( instruction.maskWith(0xE000)==0xC000 );
+ case Architecture::P18C:
+ case Architecture::P18F:
+ case Architecture::P18J: return ( instruction.maskWith(0xFF00)==0xEF00 );
+ case Architecture::P24F:
+ case Architecture::P24H:
+ case Architecture::P30F:
+ case Architecture::P33F: return ( instruction.maskWith(0xFF0000)==0x040000 );
+ case Architecture::Nb_Types: Q_ASSERT(false); break;
+ }
+ return false;
+}
+
+uint Pic::Data::nbWordsWriteAlignment(MemoryRangeType type) const
+{
+ if ( type!=MemoryRangeType::Code ) return 1;
+ return QMAX(_nbWordsCodeWrite, uint(16));
+}
+
+//----------------------------------------------------------------------------
+QDataStream &operator <<(QDataStream &s, const Pic::VoltageData &vd)
+{
+ s << vd.min << vd.max << vd.nominal;
+ return s;
+}
+QDataStream &operator >>(QDataStream &s, Pic::VoltageData &vd)
+{
+ s >> vd.min >> vd.max >> vd.nominal;
+ return s;
+}
+
+QDataStream &operator <<(QDataStream &s, const Pic::MemoryRangeData &mrd)
+{
+ s << Q_UINT8(mrd.properties) << mrd.start << mrd.end << mrd.hexFileOffset;
+ return s;
+}
+QDataStream &operator >>(QDataStream &s, Pic::MemoryRangeData &mrd)
+{
+ Q_UINT8 properties;
+ s >> properties >> mrd.start >> mrd.end >> mrd.hexFileOffset;
+ mrd.properties = Pic::MemoryRangeProperties(properties);
+ return s;
+}
+
+QDataStream &operator <<(QDataStream &s, const Pic::Checksum::Data &cd)
+{
+ s << cd.constant << cd.bbsize << cd.algorithm << cd.protectedMaskNames;
+ s << cd.blankChecksum << cd.checkChecksum;
+ return s;
+}
+QDataStream &operator >>(QDataStream &s, Pic::Checksum::Data &cd)
+{
+ s >> cd.constant >> cd.bbsize >> cd.algorithm >> cd.protectedMaskNames;
+ s >> cd.blankChecksum >> cd.checkChecksum;
+ return s;
+}
+
+QDataStream &operator <<(QDataStream &s, const Pic::CalibrationData &cd)
+{
+ s << cd.opcode << cd.opcodeMask;
+ return s;
+}
+QDataStream &operator >>(QDataStream &s, Pic::CalibrationData &cd)
+{
+ s >> cd.opcode >> cd.opcodeMask;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const Pic::Data &data)
+{
+ s << static_cast<const Device::Data &>(data);
+ s << data._architecture << data._ids << data._nbBitsPC;
+ s << data._voltages << data._ranges;
+ s << data._userIdRecommendedMask;
+ s << *data._config;
+ s << data._checksums;
+ s << data._calibration;
+ s << static_cast<const Pic::RegistersData &>(*data._registersData);
+ s << data._nbWordsCodeWrite << data._nbWordsCodeRowErase;
+ s << data._selfWrite;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, Pic::Data &data)
+{
+ s >> static_cast<Device::Data &>(data);
+ s >> data._architecture >> data._ids >> data._nbBitsPC;
+ s >> data._voltages >> data._ranges;
+ s >> data._userIdRecommendedMask;
+ s >> *data._config;
+ s >> data._checksums;
+ s >> data._calibration;
+ s >> static_cast<Pic::RegistersData &>(*data._registersData);
+ s >> data._nbWordsCodeWrite >> data._nbWordsCodeRowErase;
+ s >> data._selfWrite;
+ return s;
+}
diff --git a/src/devices/pic/base/pic.h b/src/devices/pic/base/pic.h
new file mode 100644
index 0000000..7b0dfc4
--- /dev/null
+++ b/src/devices/pic/base/pic.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+#ifndef PIC_H
+#define PIC_H
+
+#include <qstringlist.h>
+#include <qmap.h>
+
+#include "common/global/global.h"
+#include "common/common/bitvalue.h"
+#include "devices/base/generic_device.h"
+
+namespace Pic
+{
+class XmlToData;
+class Group;
+class Config;
+class RegistersData;
+
+//-----------------------------------------------------------------------------
+struct VoltageData {
+ double min, max, nominal;
+};
+inline bool operator ==(const Pic::VoltageData &v1, const Pic::VoltageData &v2) { return ( v1.min==v2.min && v1.max==v2.max && v1.nominal==v2.nominal ); }
+
+BEGIN_DECLARE_ENUM(ProgVoltageType)
+ Vpp = 0, VddBulkErase, VddWrite
+END_DECLARE_ENUM_STD(ProgVoltageType)
+
+struct CalibrationData {
+ BitValue opcode, opcodeMask;
+};
+
+enum MemoryRangeTypeProperty { ReadOnly = 0, Writable = 1 };
+Q_DECLARE_FLAGS(MemoryRangeTypeProperties, MemoryRangeTypeProperty)
+Q_DECLARE_OPERATORS_FOR_FLAGS(MemoryRangeTypeProperties)
+struct MemoryRangeTypeData {
+ const char *key, *label;
+ MemoryRangeTypeProperties properties;
+};
+BEGIN_DECLARE_ENUM(MemoryRangeType)
+ Code = 0, Cal, UserId, DeviceId, Config, Eeprom, DebugVector, HardwareStack, CalBackup, ProgramExecutive
+END_DECLARE_ENUM(MemoryRangeType, MemoryRangeTypeData)
+
+BEGIN_DECLARE_ENUM(SelfWrite)
+ Yes, No
+END_DECLARE_ENUM_STD(SelfWrite)
+
+BEGIN_DECLARE_ENUM(DeviceType)
+ Normal, J, K
+END_DECLARE_ENUM_STD(DeviceType)
+
+struct ArchitectureData {
+ const char *key, *label;
+ uint nbBitsPC; // nb bits program counter
+ uint nbBytesWord; // nb bytes per word (hex file and icd2)
+ bool packed; // addressIncrement = (packed ? nbBytesWord : nbBytesWord/2)
+ uint nbBitsRegister;
+ uint registerBankLength;
+ uint nbBits[MemoryRangeType::Nb_Types]; // nb bits per word
+ bool hasAddressAccess; // memory can be accessed randomly
+ SelfWrite::Type selfWrite;
+ DeviceType::Type deviceType;
+};
+BEGIN_DECLARE_ENUM(Architecture)
+ P10X = 0, P16X, P17C, P18C, P18F, P18J, P24F, P24H, P30F, P33F
+END_DECLARE_ENUM(Architecture, ArchitectureData)
+
+enum MemoryRangeProperty { NotPresent = 0, Present = 1, Programmable = 2 };
+Q_DECLARE_FLAGS(MemoryRangeProperties, MemoryRangeProperty)
+Q_DECLARE_OPERATORS_FOR_FLAGS(MemoryRangeProperties)
+struct MemoryRangeData {
+ MemoryRangeProperties properties;
+ Address start, end;
+ uint hexFileOffset;
+};
+
+namespace Checksum
+{
+ BEGIN_DECLARE_ENUM(Algorithm)
+ Normal = 0, XOR4, XNOR7, XNOR8
+ END_DECLARE_ENUM_STD(Algorithm)
+ class Data {
+ public:
+ BitValue constant;
+ Algorithm algorithm;
+ QStringList protectedMaskNames;
+ QString bbsize;
+ BitValue blankChecksum, checkChecksum;
+ };
+} // namespace
+
+BEGIN_DECLARE_ENUM(Feature)
+ CCP, ADC, SSP, LVD, USB, USART, CAN, ECAN, Ethernet, LCD, MotorControl,
+ MotionFeedback, SelfWrite
+END_DECLARE_ENUM_STD(Feature)
+
+//-----------------------------------------------------------------------------
+class Data : public Device::Data
+{
+public:
+ Data();
+ virtual ~Data();
+ virtual QString fname(Device::Special special) const;
+ virtual QString listViewGroup() const { return _architecture.label(); }
+ bool isPresent(MemoryRangeType type) const { return (range(type).properties & Present); }
+ bool isReadable(MemoryRangeType type) const;
+ bool isWritable(MemoryRangeType type) const;
+ uint nbAddresses(MemoryRangeType type) const;
+ uint nbWords(MemoryRangeType type) const;
+ uint addressIncrement(MemoryRangeType type) const;
+ uint nbWordsWriteAlignment(MemoryRangeType type) const;
+ MemoryRangeData range(MemoryRangeType type) const { return _ranges[type]; }
+ virtual uint nbBitsAddress() const { return _nbBitsPC; }
+ uint nbBitsWord(MemoryRangeType type) const { return _architecture.data().nbBits[type.type()]; }
+ uint nbBytesWord(MemoryRangeType type) const { return nbBitsToNbBytes(nbBitsWord(type)); }
+ uint nbCharsWord(MemoryRangeType type) const { return nbBitsToNbChars(nbBitsWord(type)); }
+ BitValue mask(MemoryRangeType type) const { return uint(1 << nbBitsWord(type))-1; }
+ BitValue userIdRecommendedMask() const { return _userIdRecommendedMask; }
+ const Config &config() const { return *_config; }
+ Architecture architecture() const { return _architecture; }
+ bool is18Family() const { return ( _architecture==Architecture::P18C || _architecture==Architecture::P18F || _architecture==Architecture::P18J); }
+ bool is16bitFamily() const { return ( _architecture.data().nbBitsRegister==16 ); }
+ VoltageData voltage(ProgVoltageType type) const { return _voltages[type]; }
+ virtual bool canWriteCalibration() const { return isWritable(MemoryRangeType::Cal); }
+ bool checkCalibration(const Device::Array &data, QString *message = 0) const;
+ const QMap<Device::Special, BitValue> ids() const { return _ids; }
+ virtual bool matchId(BitValue rawId, Device::IdData &data) const;
+ QStringList idNames(const QMap<QString, Device::IdData> &ids) const;
+ const QMap<QString, Checksum::Data> checksums() const { return _checksums; }
+ const RegistersData &registersData() const;
+ const CalibrationData &calibrationData() const { return _calibration; }
+
+ bool hasFeature(Feature feature, bool *unknown = 0) const;
+ BitValue nopInstruction() const { return 0x0; }
+ Device::Array gotoInstruction(Address address, bool withPageSelection) const;
+ bool isGotoInstruction(BitValue instruction) const;
+
+private:
+ Architecture _architecture;
+ QMap<Device::Special, BitValue> _ids;
+ uint _nbBitsPC;
+ uint _nbWordsCodeWrite; // #### only for 18F/18J devices [0 for other devices]
+ uint _nbWordsCodeRowErase; // #### only for 18F/18J devices [0 for other devices or if not available]
+ QMap<ProgVoltageType, VoltageData> _voltages;
+ QMap<MemoryRangeType, MemoryRangeData> _ranges;
+ BitValue _userIdRecommendedMask;
+ Config *_config;
+ QMap<QString, Checksum::Data> _checksums;
+ CalibrationData _calibration;
+ SelfWrite _selfWrite;
+
+ friend class XmlToData;
+ friend class Group;
+ friend QDataStream &operator <<(QDataStream &s, const Data &data);
+ friend QDataStream &operator >>(QDataStream &s, Data &data);
+};
+
+QDataStream &operator <<(QDataStream &s, const Data &data);
+QDataStream &operator >>(QDataStream &s, Data &data);
+
+} // namespace
+
+QDataStream &operator <<(QDataStream &s, const Pic::VoltageData &vd);
+QDataStream &operator >>(QDataStream &s, Pic::VoltageData &vd);
+QDataStream &operator <<(QDataStream &s, const Pic::MemoryRangeData &mrd);
+QDataStream &operator >>(QDataStream &s, Pic::MemoryRangeData &mrd);
+QDataStream &operator <<(QDataStream &s, const Pic::Checksum::Data &cd);
+QDataStream &operator >>(QDataStream &s, Pic::Checksum::Data &cd);
+QDataStream &operator <<(QDataStream &s, const Pic::CalibrationData &cd);
+QDataStream &operator >>(QDataStream &s, Pic::CalibrationData &cd);
+
+#endif
diff --git a/src/devices/pic/base/pic_config.cpp b/src/devices/pic/base/pic_config.cpp
new file mode 100644
index 0000000..6672794
--- /dev/null
+++ b/src/devices/pic/base/pic_config.cpp
@@ -0,0 +1,456 @@
+/***************************************************************************
+ * 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 "pic_config.h"
+
+#include <qregexp.h>
+
+const Pic::ConfigNameType::Data Pic::ConfigNameType::DATA[Nb_Types] = {
+ { "cname", 0 },
+ { "ecname", 0 },
+ { "sdcc_cname", 0 }
+};
+
+const Pic::Config::Data Pic::Config::DATA[] = {
+ { { "CP", I18N_NOOP("Code code-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "CPD", I18N_NOOP("Data code-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "CPC", I18N_NOOP("Calibration code-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "CPB", I18N_NOOP("Boot code-protection") }, MemoryRange, { { 0, 0 } } },
+
+ { { "WRT", I18N_NOOP("Code write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "WRTD", I18N_NOOP("Data write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "WRTB", I18N_NOOP("Boot write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "WRTC", I18N_NOOP("Configuration write-protection") }, MemoryRange, { { 0, 0 } } },
+
+ { { "EBTR", I18N_NOOP("Table read-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "EBTRB", I18N_NOOP("Boot table read-protection") }, MemoryRange, { { 0, 0 } } },
+
+ { { "WDT", I18N_NOOP("Watchdog timer") }, Toggle, { { 0, 0 } } },
+ { { "MCLRE", I18N_NOOP("Master clear reset"), }, Fixed, {
+ { "External", I18N_NOOP("External"), },
+ { "Internal", I18N_NOOP("Disabled (connected to Vdd)") }, { 0, 0 } } },
+ { { "PWRTE", I18N_NOOP("Power-up timer") }, Toggle, { { 0, 0 } } },
+
+ { { "FOSC", I18N_NOOP("Oscillator") }, Fixed, {
+ { "EXTRC", I18N_NOOP("External RC oscillator") },
+ { "EXTRC_CLKOUT", I18N_NOOP("External RC oscillator with CLKOUT") },
+ { "EXTRC_IO", I18N_NOOP("External RC oscillator (no CLKOUT)") },
+ { "INTRC", I18N_NOOP("Internal oscillator") },
+ { "INTRC_CLKOUT", I18N_NOOP("Internal oscillator with CLKOUT") },
+ { "INTRC_IO", I18N_NOOP("Internal oscillator (no CLKOUT)") },
+ { "XT", I18N_NOOP("Crystal/resonator") },
+ { "XTPLL", I18N_NOOP("Crystal/resonator, PLL enabled") },
+ { "LP", I18N_NOOP("Low power crystal") },
+ { "EC", I18N_NOOP("External clock") },
+ { "EC_CLKOUT", I18N_NOOP("External clock with CLKOUT") },
+ { "EC_IO", I18N_NOOP("External clock (no CLKOUT)") },
+ { "ECPLL_CLKOUT", I18N_NOOP("External clock with CLKOUT, PLL enabled") },
+ { "ECPLL_IO", I18N_NOOP("External clock (no CLKOUT), PLL enabled") },
+ { "E4_CLKOUT", I18N_NOOP("External clock with 4x PLL and with CLKOUT") },
+ { "E4_IO", I18N_NOOP("External clock with 4x PLL (no CLKOUT)") },
+ { "E4S_IO", I18N_NOOP("External clock with software controlled 4x PLL (no CLKOUT)") },
+ { "ER", I18N_NOOP("External resistor") },
+ { "ER_CLKOUT", I18N_NOOP("External resistor with CLKOUT") },
+ { "ER_IO", I18N_NOOP("External resistor (no CLKOUT)") },
+ { "HS", I18N_NOOP("High speed crystal/resonator") },
+ { "HSPLL", I18N_NOOP("High speed crystal/resonator, PLL enabled") },
+ { "H4", I18N_NOOP("High speed crystal/resonator with 4x PLL") },
+ { "H4S", I18N_NOOP("High speed crystal/resonator with software controlled 4x PLL") },
+ { "INTXT", I18N_NOOP("Internal oscillator, XT used by USB") },
+ { "INTHS", I18N_NOOP("Internal oscillator, HS used by USB") },
+ { 0, 0 } } },
+
+ { { "BG", I18N_NOOP("Bandgap voltage calibration") }, Fixed, {
+ { "Lowest", I18N_NOOP("Lowest") },
+ { "Mid/Low", I18N_NOOP("Mid/Low") },
+ { "Mid/High", I18N_NOOP("Mid/High") },
+ { "Highest", I18N_NOOP("Highest") }, { 0, 0 } } },
+ { { "TRIM", I18N_NOOP("Internal Trim") }, Fixed, {
+ { "00", I18N_NOOP("00") }, { "01", I18N_NOOP("01") },
+ { "10", I18N_NOOP("10") }, { "11", I18N_NOOP("11") }, { 0, 0 } } },
+ { { "BODEN", I18N_NOOP("Brown-out detect") }, Toggle, {
+ { "On_run", I18N_NOOP("Enabled in run - Disabled in sleep") },
+ { "Software", I18N_NOOP("SBODEN controls BOD function") }, { 0, 0 } } },
+ { { "FCMEN", I18N_NOOP("Fail-safe clock monitor") }, Toggle, { { 0, 0 } } },
+ { { "IESO", I18N_NOOP("Internal-external switchover") }, Toggle, { { 0, 0 } } },
+ { { "WUREN", I18N_NOOP("Wake-up reset") }, Toggle, { { 0, 0 } } },
+ { { "DEBUG", I18N_NOOP("In-circuit debugger") }, Toggle, { { 0, 0 } } },
+ { { "MPEEN", I18N_NOOP("Memory parity error") }, Toggle, { { 0, 0 } } },
+ { { "BORV", I18N_NOOP("Brown-out reset voltage") }, ValueDouble, {
+ { "0", I18N_NOOP("Undefined") }, { 0, 0 } } },
+ { { "LVP", I18N_NOOP("Low voltage programming") }, Toggle, { { 0, 0 } } },
+ { { "CCP2MX", I18N_NOOP("CCP2 multiplex") }, Pin, { { 0, 0 } } },
+ { { "CCP1MX", I18N_NOOP("CCP1 multiplex") }, Pin, { { 0, 0 } } },
+ { { "BORSEN", I18N_NOOP("Brown-out reset software") }, Toggle, { { 0, 0 } } },
+ { { "WDTPS", I18N_NOOP("WDT post-scaler") }, Ratio, {
+ { "Disabled", I18N_NOOP("Disabled") }, { 0, 0 } } },
+ { { "PM", I18N_NOOP("Processor mode") }, Fixed, {
+ { "Extended microcontroller", I18N_NOOP("Extended microcontroller") },
+ { "Microcontroller", I18N_NOOP("Microcontroller") },
+ { "Microprocessor", I18N_NOOP("Microprocessor") },
+ { "Code-protected microcontroller", I18N_NOOP("Code protected microcontroller") },
+ { "Microprocessor with boot", I18N_NOOP("Microprocessor with boot block") },
+ { 0, 0 } } },
+
+ { { "OSCSEN", I18N_NOOP("Oscillator system clock switch") }, Toggle, { { 0, 0 } } },
+ { { "STVREN", I18N_NOOP("Stack full/underflow reset") }, Toggle, { { 0, 0 } } },
+ { { "BW", I18N_NOOP("External bus data width (in bits)") }, ValueUInt, { { 0, 0 } } },
+ { { "PBADEN", I18N_NOOP("PORTB A/D") }, Fixed, {
+ { "digital", I18N_NOOP("Digital") },
+ { "analog", I18N_NOOP("Analog") }, { 0, 0 } } },
+ { { "WINEN", I18N_NOOP("Watchdog timer window") }, Toggle, { { 0, 0 } } },
+ { { "HPOL", I18N_NOOP("Odd PWM output polarity") }, Fixed, {
+ { "high", I18N_NOOP("Active high") },
+ { "low", I18N_NOOP("Active low") }, { 0, 0 } } },
+ { { "LPOL", I18N_NOOP("Even PWM output polarity") }, Fixed, {
+ { "high", I18N_NOOP("Active high") },
+ { "low", I18N_NOOP("Active low") }, { 0, 0 } } },
+ { { "PWMPIN", I18N_NOOP("PWM output pin reset state") }, Toggle, { { 0, 0 } } },
+ { { "T1OSCMX", I18N_NOOP("Timer1 oscillator mode") }, Fixed, {
+ { "Legacy", I18N_NOOP("Standard operation") },
+ { "Low Power", I18N_NOOP("Low power in sleep mode") },
+ { "RA6", I18N_NOOP("T1OSO/T1CKI on RA6") },
+ { "RB2", I18N_NOOP("T1OSO/T1CKI on RB2") }, { 0, 0 } } },
+ { { "EXCLKMX", I18N_NOOP("TMR0/T5CKI external clock mux") }, Pin, { { 0, 0 } } },
+ { { "FLTAMX", I18N_NOOP("FLTA mux") }, Pin, { { 0, 0 } } },
+ { { "PWM4MX", I18N_NOOP("PWM4 mux") }, Pin, { { 0, 0 } } },
+ { { "SSPMX", I18N_NOOP("SSP I/O mux (SCK/SLC, SDA/SDI, SD0)") }, Pins, { { 0, 0 } } },
+ { { "LPT1OSC", I18N_NOOP("Low-power timer1 oscillator") }, Toggle, { { 0, 0 } } },
+ { { "XINST", I18N_NOOP("Extended instruction set") }, Toggle, { { 0, 0 } } },
+ { { "BBSIZ", I18N_NOOP("Boot block size") }, ValueUInt, { { 0, 0 } } },
+ { { "ICPORT", I18N_NOOP("Dedicated in-circuit port") }, Toggle, { { 0, 0 } } },
+ { { "VREGEN", I18N_NOOP("USB voltage regulator") }, Toggle, { { 0, 0 } } },
+ { { "WAIT", I18N_NOOP("External bus data wait") }, Toggle, { { 0, 0 } } },
+ { { "ABW", I18N_NOOP("Address bus width (in bits)") }, ValueUInt, { { 0, 0 } } },
+ { { "ECCPMX", I18N_NOOP("ECCP mux") }, Fixed, {
+ { "RE6-RE3", I18N_NOOP("PWM multiplexed onto RE6 and RE3") },
+ { "RH7-RH4", I18N_NOOP("PWM multiplexed onto RH7 and RH4") },
+ { "RE6-RE5", I18N_NOOP("PWM multiplexed onto RE6 and RE5") },
+ { "RH7-RH6", I18N_NOOP("PWM multiplexed onto RH7 and RH6") }, { 0, 0 } } },
+
+ { { "FCKSM", I18N_NOOP("Clock switching mode") }, Fixed, {
+ { "Switching off, monitor off", I18N_NOOP("Switching off, monitor off") },
+ { "Switching on, monitor off", I18N_NOOP("Switching on, monitor off") },
+ { "Switching on, monitor on", I18N_NOOP("Switching on, monitor on") }, { 0, 0 } } },
+ { { "FOS", I18N_NOOP("Oscillator source") }, Fixed, {
+ { "INTRC_F", I18N_NOOP("Internal fast RC") },
+ { "INTRC_LP", I18N_NOOP("Internal low-power RC") },
+ { "PRIM", I18N_NOOP("Primary") },
+ { "TMR1", I18N_NOOP("Timer1") }, { 0, 0 } } },
+ { { "FPR", I18N_NOOP("Primary oscillator mode") }, Fixed, {
+ { "XTL", I18N_NOOP("Low-power/low-frequency crystal") },
+ { "HS", I18N_NOOP("High speed crystal") },
+ { "XT", I18N_NOOP("XT Crystal") },
+ { "XT4", I18N_NOOP("XT Crystal with 4x PLL") },
+ { "XT8", I18N_NOOP("XT Crystal with 8x PLL") },
+ { "XT16", I18N_NOOP("XT Crystal with 16x PLL") },
+ { "EC_CLKOUT", I18N_NOOP("External clock with CLKOUT") },
+ { "EC_IO", I18N_NOOP("External clock (no CLKOUT)") },
+ { "EC4", I18N_NOOP("External clock with 4x PLL") },
+ { "EC8", I18N_NOOP("External clock with 8x PLL") },
+ { "EC16", I18N_NOOP("External clock with 16x PLL") },
+ { "FRC8", I18N_NOOP("Internal fast RC oscillator with 8x PLL") },
+ { "EXTRC_CLKOUT", I18N_NOOP("External RC oscillator with CLKOUT") },
+ { "EXTRC_IO", I18N_NOOP("External RC oscillator (no CLKOUT)") }, { 0, 0 } } },
+ { { "FOSFPR", I18N_NOOP("Oscillator mode") }, Fixed, {
+ { "XTL", I18N_NOOP("Low-power/low-frequency crystal") },
+ { "HS", I18N_NOOP("High speed crystal") },
+ { "XT", I18N_NOOP("XT Crystal") },
+ { "XT4", I18N_NOOP("XT Crystal with 4x PLL") },
+ { "XT8", I18N_NOOP("XT Crystal with 8x PLL") },
+ { "XT16", I18N_NOOP("XT Crystal with 16x PLL") },
+ { "HS2_4", I18N_NOOP("HS/2 Crystal with 4x PLL") },
+ { "HS2_8", I18N_NOOP("HS/2 Crystal with 8x PLL") },
+ { "HS2_16", I18N_NOOP("HS/2 Crystal with 16x PLL") },
+ { "HS3_4", I18N_NOOP("HS/3 Crystal with 4x PLL") },
+ { "HS3_8", I18N_NOOP("HS/3 Crystal with 8x PLL") },
+ { "HS3_16", I18N_NOOP("HS/3 Crystal with 16x PLL") },
+ { "EC_CLKOUT", I18N_NOOP("External clock with CLKOUT") },
+ { "EC_IO", I18N_NOOP("External clock (no CLKOUT)") },
+ { "EC4", I18N_NOOP("External clock with 4x PLL") },
+ { "EC8", I18N_NOOP("External clock with 8x PLL") },
+ { "EC16", I18N_NOOP("External clock with 16x PLL") },
+ { "FRC4", I18N_NOOP("Internal fast RC oscillator with 4x PLL") },
+ { "FRC8", I18N_NOOP("Internal fast RC oscillator with 8x PLL") },
+ { "FRC16", I18N_NOOP("Internal fast RC oscillator with 16x PLL") },
+ { "TMR1", I18N_NOOP("Low-power 32 kHz oscillator (TMR1 oscillator)") },
+ { "INTRC_F", I18N_NOOP("Internal fast RC oscillator (no PLL)") },
+ { "INTRC_LP", I18N_NOOP("Internal low-power RC oscillator") },
+ { "EXTRC_CLKOUT", I18N_NOOP("External RC oscillator with CLKOUT") },
+ { "EXTRC_IO", I18N_NOOP("External RC oscillator (no CLKOUT)") }, { 0, 0 } } },
+ { { "FWPSA", I18N_NOOP("Watchdog timer prescaler A") }, Ratio, { { 0, 0 } } },
+ { { "FWPSB", I18N_NOOP("Watchdog timer prescaler B") }, Ratio, { { 0, 0 } } },
+ { { "FWDTEN", I18N_NOOP("Watchdog") }, Toggle, {
+ { "Software", I18N_NOOP("Software") }, { 0, 0 } } },
+ { { "FPWRT", I18N_NOOP("Power-on reset timer value (ms)") }, ValueUInt, {
+ { "0", I18N_NOOP("Disabled") }, { 0, 0 } } },
+ { { "GCP", I18N_NOOP("General code segment read-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "GWRP", I18N_NOOP("General code segment write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "COE", I18N_NOOP("Reset into clip on emulation mode") }, Toggle, { { 0, 0 } } },
+ { { "ICS", I18N_NOOP("ICD communication channel") }, Pins, { { 0, 0 } } },
+
+ { { "USBDIV", I18N_NOOP("USB clock (PLL divided by)") }, ValueUInt, {
+ { "1", I18N_NOOP("not divided") }, { 0, 0 } } },
+ { { "CPUDIV", I18N_NOOP("CPU system clock (divided by)") }, ValueUInt, {
+ { "1", I18N_NOOP("not divided") }, { 0, 0 } } },
+ { { "PLLDIV", I18N_NOOP("PLL clock (divided by)") }, ValueUInt, {
+ { "1", I18N_NOOP("not divided") }, { 0, 0 } } },
+
+ { { "MCPU", I18N_NOOP("Master clear pull-up resistor") }, Toggle, { { 0, 0 } } },
+ { { "IOSCFS", I18N_NOOP("Internal oscillator speed") }, Fixed, {
+ { "8MHZ", I18N_NOOP("8 MHz") },
+ { "4MHZ", I18N_NOOP("4 MHz") }, { 0, 0 } } },
+
+ // 18J specific
+ { { "ETHLED", I18N_NOOP("Ethernet LED enable") }, Toggle, { { 0, 0 } } },
+ { { "FOSC2", I18N_NOOP("Default system clock select") }, Fixed, {
+ { "FOSC1:FOSC0", I18N_NOOP("FOSC1:FOSC0") },
+ { "INTRC", I18N_NOOP("INTRC") }, { 0, 0 } } },
+ { { "EMB", I18N_NOOP("External memory bus") }, Fixed, {
+ { "Disabled", I18N_NOOP("Disabled") },
+ { "12BIT", I18N_NOOP("12-bit external bus") },
+ { "16BIT", I18N_NOOP("16-bit external bus") },
+ { "20BIT", I18N_NOOP("20-bit external bus") }, { 0, 0 } } },
+ { { "EASHFT", I18N_NOOP("External address bus shift") }, Toggle, { { 0, 0 } } },
+ { { "MSSPSEL", I18N_NOOP("MSSP address select bit") }, Fixed, {
+ { "7BIT", I18N_NOOP("7-bit address mask mode") },
+ { "5BIT", I18N_NOOP("5-bit address mask mode") }, { 0, 0 } } },
+ { { "PMPMX", I18N_NOOP("PMP pin select bit") }, Fixed, {
+ { "Connected", I18N_NOOP("Connected to EMB") },
+ { "NotConnected", I18N_NOOP("Not connected to EMB") }, { 0, 0 } } },
+
+ // 24X specific / 30F1010 / 30F202X
+ { { "WRTBS", I18N_NOOP("Boot segment write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "BSSIZ", I18N_NOOP("Boot segment size") }, ValueUInt, { { 0, 0 } } },
+ { { "BSSEC", I18N_NOOP("Boot segment security") }, Fixed, {
+ { "High Security", I18N_NOOP("High Security") },
+ { "Standard Security", I18N_NOOP("Standard Security") }, { 0, 0 } } },
+ { { "EBSSIZ", I18N_NOOP("Boot segment EEPROM size") }, ValueUInt, { { 0, 0 } } },
+ { { "RBSSIZ", I18N_NOOP("Boot segment RAM size") }, ValueUInt, { { 0, 0 } } },
+ { { "WRTSS", I18N_NOOP("Secure segment write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "SSSIZ", I18N_NOOP("Secure segment size") }, ValueUInt, { { 0, 0 } } },
+ { { "SSSEC", I18N_NOOP("Secure segment security") }, Fixed, {
+ { "High Security", I18N_NOOP("High Security") },
+ { "Standard Security", I18N_NOOP("Standard Security") }, { 0, 0 } } },
+ { { "ESSSIZ", I18N_NOOP("Secure segment EEPROM size") }, ValueUInt, { { 0, 0 } } },
+ { { "RSSSIZ", I18N_NOOP("Secure segment RAM size") }, ValueUInt, { { 0, 0 } } },
+ { { "WRTGS", I18N_NOOP("General segment write-protection") }, MemoryRange, { { 0, 0 } } },
+ { { "GSSEC", I18N_NOOP("General segment security") }, Fixed, {
+ { "Off", I18N_NOOP("Off") },
+ { "High Security", I18N_NOOP("High security") },
+ { "Standard Security", I18N_NOOP("Standard security") }, { 0, 0 } } },
+ { { "FNOSC", I18N_NOOP("Initial oscillator source") }, Fixed, {
+ { "EXTRC_F" , I18N_NOOP("Fast RC oscillator") },
+ { "INTRC_F", I18N_NOOP("Internal fast RC oscillator") },
+ { "INTRC_F_PLL", I18N_NOOP("Internal fast RC oscillator with PLL") },
+ { "PRIM", I18N_NOOP("Primary oscillator") },
+ { "PRIM_PLL", I18N_NOOP("Primary oscillator with PLL") },
+ { "SECOND", I18N_NOOP("Secondary oscillator (LP)") },
+ { "EXTRC_LP", I18N_NOOP("Low power RC oscillator") },
+ { "INTRC_F_POST", I18N_NOOP("Internal fast RC oscillator with postscaler") }, { 0, 0 } } },
+ { { "POSCMD", I18N_NOOP("Primary oscillator mode") }, Fixed, {
+ { "Off", I18N_NOOP("Off") },
+ { "HS", I18N_NOOP("HS crystal oscillator") },
+ { "XT", I18N_NOOP("XT crystal oscillator") },
+ { "EC", I18N_NOOP("External clock") }, { 0, 0 } } },
+ { { "TEMP", I18N_NOOP("Temperature protection") }, Toggle, { { 0, 0 } } },
+ { { "OSCIOFNC", I18N_NOOP("OSC2 pin function") }, Fixed, {
+ { "IO", I18N_NOOP("Digital I/O") },
+ { "Clock", I18N_NOOP("Clock output") }, { 0, 0 } } },
+ { { "WINDIS", I18N_NOOP("Watchdog timer window") }, Toggle, { { 0, 0 } } },
+ { { "WDTPRE", I18N_NOOP("Watchdog timer prescaler") }, Ratio, { { 0, 0 } } },
+ { { "WDTPOST", I18N_NOOP("Watchdog timer postscaler") }, Ratio, { { 0, 0 } } },
+ { { "JTAGEN", I18N_NOOP("JTAG port enabled") }, Toggle, { { 0, 0 } } },
+ { { "IOL1WAY", I18N_NOOP("Peripheral pin select configuration") }, Fixed, {
+ { "One reconfiguration", I18N_NOOP("Allow only one reconfiguration") },
+ { "Multiple reconfigurations", I18N_NOOP("Allow multiple reconfigurations") }, { 0, 0 } } },
+ { { "ALTI2C", I18N_NOOP("Alternate I2C pins") }, Pin, { { 0, 0 } } },
+ { { "I2C1SEL", I18N_NOOP("I2C pins selection") }, Fixed, {
+ { "Default", I18N_NOOP("Default") },
+ { "Alternate", I18N_NOOP("Alternate") }, { 0, 0 } } },
+ { { "FRANGE", I18N_NOOP("Frequency range selection for FRC oscillator") }, Fixed, {
+ { "High range", I18N_NOOP("High range (nominal FRC frequency is 14.1 MHz)") },
+ { "Low range", I18N_NOOP("Low range (nominal FRC frequency is 9.7 MHz)") }, { 0, 0 } } },
+
+ { { 0, 0 }, Fixed, { { 0, 0 } } }
+};
+
+QMap<QString, Pic::Config::MapData> *Pic::Config::_masks = 0;
+QMap<QString, Pic::Config::MapData> &Pic::Config::masks()
+{
+ if ( _masks==0 ) {
+ _masks = new QMap<QString, MapData>;
+ for (uint i=0; DATA[i].mask.name; i++) {
+ (*_masks)[DATA[i].mask.name] = MapData(i, -1);
+ if ( DATA[i].type==MemoryRange ) {
+ for (uint k=0; k<Protection::MAX_NB_BLOCKS; k++)
+ (*_masks)[QString("%1_%2").arg(DATA[i].mask.name).arg(k)] = MapData(i, k);
+ }
+ }
+ }
+ return *_masks;
+}
+
+bool Pic::Config::hasMaskName(const QString &mask)
+{
+ return masks().contains(mask);
+}
+
+QString Pic::Config::maskLabel(const QString &mask)
+{
+ const MapData &mp = masks()[mask];
+ QString s = i18n(DATA[mp.index].mask.label);
+ if ( mp.block>=0 ) return i18n("%1 for block %2").arg(s).arg(mp.block);
+ return s;
+}
+
+const Pic::Config::Mask *Pic::Config::findMask(const QString &mask, uint *wordIndex) const
+{
+ for (uint i=0; i<uint(_words.count()); i++)
+ for (uint k=0; k<uint(_words[i].masks.count()); k++) {
+ if ( _words[i].masks[k].name==mask ) {
+ if (wordIndex) *wordIndex = i;
+ return &_words[i].masks[k];
+ }
+ }
+ return 0;
+}
+
+const Pic::Config::Value *Pic::Config::findValue(const QString &mask, const QString &value) const
+{
+ const Mask *cmask = findMask(mask);
+ if ( cmask==0 ) return 0;
+ for (uint i=0; i<uint(cmask->values.count()); i++)
+ if ( cmask->values[i].name==value ) return &cmask->values[i];
+ return 0;
+}
+
+bool Pic::Config::checkValueName(const QString &mask, const QString &name) const
+{
+ const Data &data = DATA[masks()[mask].index];
+ QString pinRegexp = "[A-Z]+\\d*(/[A-Z]+\\d*)?";
+ switch (data.type) {
+ case Fixed: break;
+ case ValueDouble: {
+ bool ok;
+ (void)name.toDouble(&ok);
+ if (ok) return true;
+ break;
+ }
+ case ValueUInt: {
+ bool ok;
+ (void)name.toUInt(&ok);
+ if (ok) return true;
+ break;
+ }
+ case Ratio: {
+ QRegExp regexp("(\\d+):(\\d+)");
+ if ( regexp.exactMatch(name) ) {
+ bool ok1, ok2;
+ (void)regexp.cap(1).toUInt(&ok1);
+ (void)regexp.cap(2).toUInt(&ok2);
+ if ( ok1 && ok2 ) return true;
+ }
+ break;
+ }
+ case MemoryRange:
+ return _protection.checkRange(mask, name);
+ case Toggle:
+ if ( name=="On" || name=="Off" ) return true;
+ break;
+ case Pin: {
+ QRegExp regexp(pinRegexp);
+ if ( regexp.exactMatch(name) ) return true;
+ break;
+ }
+ case Pins: {
+ QRegExp regexp(pinRegexp + "(, " + pinRegexp + ")+");
+ if ( regexp.exactMatch(name) ) return true;
+ break;
+ }
+ }
+ for (uint i=0; data.values[i].name; i++)
+ if ( data.values[i].name==name ) return true;
+ return false;
+}
+
+QString Pic::Config::valueLabel(const QString &mask, const QString &name)
+{
+ const Data &data = DATA[masks()[mask].index];
+ switch (data.type) {
+ case Fixed:
+ case ValueDouble:
+ case ValueUInt:
+ case Pin:
+ case Pins:
+ case Ratio: break;
+ case MemoryRange:
+ if ( name=="All" ) return i18n("All");
+ if ( name=="Off" ) return i18n("Disabled");
+ break;
+ case Toggle:
+ if ( name=="On" ) return i18n("Enabled");
+ if ( name=="Off" ) return i18n("Disabled");
+ break;
+ }
+ for (uint i=0; data.values[i].name; i++)
+ if ( data.values[i].name==name ) return i18n(data.values[i].label);
+ return name;
+}
+
+BitValue Pic::Config::Word::usedMask() const
+{
+ BitValue mask = 0x0;
+ for (uint i=0; i<uint(masks.count()); i++) mask |= masks[i].value;
+ return mask;
+}
+
+//-----------------------------------------------------------------------------
+QDataStream &Pic::operator <<(QDataStream &s, const Config::Value &value)
+{
+ s << value.name << value.configNames << value.value;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, Config::Value &value)
+{
+ s >> value.name >> value.configNames >> value.value;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const Config::Mask &mask)
+{
+ s << mask.name << mask.value << mask.values;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, Config::Mask &mask)
+{
+ s >> mask.name >> mask.value >> mask.values;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const Config::Word &word)
+{
+ s << word.name << word.ignoredCNames << word.wmask << word.pmask << word.cmask << word.bvalue << word.masks;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, Config::Word &word)
+{
+ s >> word.name >> word.ignoredCNames >> word.wmask >> word.pmask >> word.cmask >> word.bvalue >> word.masks;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const Config &config)
+{
+ s << config._words;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, Config &config)
+{
+ s >> config._words;
+ return s;
+}
diff --git a/src/devices/pic/base/pic_config.h b/src/devices/pic/base/pic_config.h
new file mode 100644
index 0000000..185a19e
--- /dev/null
+++ b/src/devices/pic/base/pic_config.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+#ifndef PIC_CONFIG_H
+#define PIC_CONFIG_H
+
+#include <qmap.h>
+#include <qstringlist.h>
+
+#include "common/common/bitvalue.h"
+#include "pic_protection.h"
+#include "pic.h"
+
+namespace Pic
+{
+class Data;
+
+BEGIN_DECLARE_ENUM(ConfigNameType)
+ Default = 0, Extra, SDCC
+END_DECLARE_ENUM_STD(ConfigNameType)
+
+class Config
+{
+public:
+ class Value {
+ public:
+ QString name;
+ QMap<ConfigNameType, QStringList> configNames;
+ BitValue value;
+ bool operator <(const Value &cv) const { return value<cv.value; }
+ bool isValid() const { return !name.isEmpty(); }
+ };
+
+ class Mask {
+ public:
+ QString name;
+ BitValue value;
+ QValueVector<Value> values; // ordered from lower to higher
+ bool operator <(const Mask &cm) const { return value<cm.value; }
+ };
+
+ class Word {
+ public:
+ QString name;
+ QStringList ignoredCNames;
+ BitValue wmask, pmask, cmask; // write, protected, and checksum bits masks
+ BitValue bvalue; // blank value
+ QValueVector<Mask> masks; // ordered from lower to higher
+ BitValue usedMask() const;
+ };
+
+public:
+ Config(const Pic::Data &data) : _data(data), _protection(data, *this) {}
+ QValueVector<Word> _words;
+ const Protection &protection() const { return _protection; }
+
+ const Value *findValue(const QString &mask, const QString &value) const;
+ const Mask *findMask(const QString &mask, uint *wordIndex = 0) const;
+ static bool hasMaskName(const QString &mask);
+ static QString maskLabel(const QString &mask);
+ bool checkValueName(const QString &mask, const QString &name) const;
+ static QString valueLabel(const QString &mask, const QString &name);
+
+private:
+ class MapData {
+ public:
+ MapData() {}
+ MapData(int i, int b) : index(i), block(b) {}
+ int index, block;
+ };
+ static QMap<QString, MapData> &masks();
+ static QMap<QString, MapData> *_masks; // mask name -> index in DATA
+
+ struct NameData {
+ const char *name, *label;
+ };
+ enum Type { Fixed, ValueDouble, ValueUInt, Ratio, MemoryRange, Toggle, Pin, Pins };
+ class Data {
+ public:
+ const NameData mask;
+ Type type;
+ const NameData values[50];
+ };
+ static const Data DATA[];
+
+private:
+ const Pic::Data &_data;
+ Protection _protection;
+};
+
+QDataStream &operator <<(QDataStream &s, const Config::Value &value);
+QDataStream &operator >>(QDataStream &s, Config::Value &value);
+QDataStream &operator <<(QDataStream &s, const Config::Mask &mask);
+QDataStream &operator >>(QDataStream &s, Config::Mask &mask);
+QDataStream &operator <<(QDataStream &s, const Config::Word &word);
+QDataStream &operator >>(QDataStream &s, Config::Word &word);
+QDataStream &operator <<(QDataStream &s, const Config &config);
+QDataStream &operator >>(QDataStream &s, Config &config);
+
+} //namespace
+
+#endif
diff --git a/src/devices/pic/base/pic_protection.cpp b/src/devices/pic/base/pic_protection.cpp
new file mode 100644
index 0000000..da77881
--- /dev/null
+++ b/src/devices/pic/base/pic_protection.cpp
@@ -0,0 +1,361 @@
+/***************************************************************************
+ * 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 "pic_protection.h"
+
+#include "pic_config.h"
+
+#include <qregexp.h>
+
+bool Pic::Protection::isNoneProtectedValueName(const QString &name) const
+{
+ if ( name=="Off" ) return true;
+ if ( _data.architecture()==Architecture::P17C ) return !isAllProtectedValueName(name);
+ return false;
+}
+
+bool Pic::Protection::isAllProtectedValueName(const QString &name) const
+{
+ if ( name=="All" ) return true;
+ if ( _data.architecture()==Architecture::P17C ) return ( name=="Code-protected microcontroller" );
+ return false;
+}
+
+Pic::Protection::Family Pic::Protection::family() const
+{
+ if ( _config.findMask("WRTBS") ) return CodeGuard;
+ QString mask = maskName(ProgramProtected, MemoryRangeType::Code);
+ if ( _config.findMask(QString("%1_%2").arg(mask).arg(0)) ) return BlockProtection;
+ if ( _config.findMask(mask) ) return BasicProtection;
+ return NoProtection;
+}
+
+QString Pic::Protection::securityValueName(Type type) const
+{
+ if ( type==StandardSecurity ) return "Standard Security";
+ if ( type==HighSecurity ) return "High Security";
+ Q_ASSERT( type==Nb_Types );
+ return "Off";
+}
+
+QString Pic::Protection::bootSizeMaskName() const
+{
+ return (family()==CodeGuard ? "BSSIZ" : "BBSIZ");
+}
+
+QString Pic::Protection::bootMaskName(Type type) const
+{
+ Q_ASSERT( type!=Nb_Types );
+ if ( family()==CodeGuard ) {
+ if ( type==WriteProtected ) return "WRTBS";
+ if ( type==StandardSecurity || type==HighSecurity ) return "BSSEC";
+ } else {
+ if ( type==ProgramProtected ) return "CPB";
+ if ( type==WriteProtected ) return "WRTB";
+ if ( type==ReadProtected ) return "EBTRB";
+ }
+ return QString::null;
+}
+
+QString Pic::Protection::blockSizeMaskName(uint block) const
+{
+ if ( family()==CodeGuard ) {
+ Q_ASSERT( block==0 );
+ return "SSSIZ";
+ }
+ return blockMaskName(ProgramProtected, block);
+}
+
+QString Pic::Protection::blockMaskName(Type type, uint block) const
+{
+ Q_ASSERT( type!=Nb_Types );
+ if ( family()==CodeGuard ) {
+ if ( type==WriteProtected ) return (block==0 ? "WRTSS" : "WRTGS");
+ if ( type==StandardSecurity || type==HighSecurity ) return (block==0 ? "SSSEC" : "GSSEC");
+ return QString::null;
+ }
+ return QString("%1_%2").arg(maskName(type, MemoryRangeType::Code)).arg(block);
+}
+
+QString Pic::Protection::maskName(Type type, MemoryRangeType mtype) const
+{
+ Q_ASSERT( type!=Nb_Types );
+ switch (mtype.type()) {
+ case MemoryRangeType::Code:
+ if ( type==ProgramProtected ) {
+ if ( _data.architecture()==Architecture::P17C ) return "PM";
+ if ( _data.architecture()==Architecture::P30F || _data.architecture()==Architecture::P24F ) return "GCP";
+ return "CP";
+ }
+ if ( type==WriteProtected ) {
+ if ( _data.architecture()==Architecture::P30F || _data.architecture()==Architecture::P24F ) return "GWRP";
+ return "WRT";
+ }
+ if ( type==ReadProtected ) return "EBTR";
+ break;
+ case MemoryRangeType::Eeprom:
+ if ( type==ProgramProtected ) return "CPD";
+ if ( type==WriteProtected ) return "WRTD";
+ break;
+ case MemoryRangeType::Cal:
+ if ( type==ProgramProtected ) return "CPC";
+ break;
+ case MemoryRangeType::Config:
+ if ( type==WriteProtected ) return "WRTC";
+ if ( type==ReadProtected ) return "EBTRC";
+ break;
+ case MemoryRangeType::Nb_Types: Q_ASSERT(false); break;
+ default: break;
+ }
+ return QString::null;
+}
+
+bool Pic::Protection::extractRanges(const QString &name, QValueVector<Address> &starts, Address &end, bool &ok)
+{
+ ok = false;
+ QRegExp regexp("([A-F0-9]+)(/[A-F0-9]+)?(/[A-F0-9]+)?:([A-F0-9]+)");
+ if ( !regexp.exactMatch(name) ) return false;
+ bool ok1;
+ end = fromHex(regexp.cap(regexp.numCaptures()), &ok1);
+ if ( !ok1 ) {
+ qDebug("Malformed end address");
+ return true;
+ }
+ starts.clear();
+ for (int i=1; i<regexp.numCaptures(); i++) {
+ if ( regexp.cap(i).isEmpty() ) break;
+ bool ok1;
+ QString s = (i==1 ? regexp.cap(i) : regexp.cap(i).mid(1));
+ Address start = fromHex(s, &ok1);
+ if ( !ok1 ) {
+ qDebug("Malformed start address %s", s.latin1());
+ return true;
+ }
+ if ( start>=end && (starts.count()==0 || starts[starts.count()-1]<start) ) {
+ qDebug("Start addresses should be ordered");
+ return true;
+ }
+ starts.append(start);
+ }
+ ok = true;
+ return true;
+}
+
+AddressRangeVector Pic::Protection::extractRanges(const QString &name, MemoryRangeType type) const
+{
+ if ( isNoneProtectedValueName(name) ) return AddressRange();
+ if ( isAllProtectedValueName(name) ) {
+ const MemoryRangeData &rdata = _data.range(type);
+ return AddressRange(rdata.start, rdata.end);
+ }
+ bool ok1;
+ QValueVector<Address> starts;
+ Address end;
+ bool ok2 = extractRanges(name, starts, end, ok1);
+ Q_ASSERT(ok1);
+ Q_ASSERT(ok2);
+ Q_UNUSED(ok2);
+ AddressRangeVector rv;
+ for (uint i=0; i<uint(starts.count()); i++) rv.append(AddressRange(starts[i], end));
+ return rv;
+}
+
+bool Pic::Protection::checkRange(const QString &mask, const QString &name) const
+{
+ if ( family()!=CodeGuard ) {
+ bool ok;
+ (void)extractRange(mask, name, ok);
+ return ok;
+ }
+
+ bool isBootBlock = false;
+ int block = 0;
+ Type ptype = Nb_Types;
+ for (uint i=0; i<3; i++) {
+ isBootBlock = ( i==0 );
+ block = i - 1;
+ for (uint k=0; k<Nb_Types; k++) {
+ QString mname = (isBootBlock ? bootMaskName(Type(k)) : blockMaskName(Type(k), block));
+ if ( mask!=mname ) continue;
+ ptype = Type(k);
+ break;
+ }
+ if ( ptype!=Nb_Types ) break;
+ }
+ if ( ptype==Nb_Types ) {
+ qDebug("Unknown protected memory range");
+ return false;
+ }
+ // #### TODO
+ return true;
+}
+
+Pic::Protection::ProtectedRange Pic::Protection::extractRange(const QString &mask, const QString &name, bool &ok) const
+{
+ Q_ASSERT( family()!=CodeGuard );
+ //qDebug("extract range %s %s", mask.latin1(), name.latin1());
+ ProtectedRange pr;
+ ok = false;
+
+ QRegExp rexp("([A-Z]+)(?:_([0-9])|)");
+ if ( !rexp.exactMatch(mask) ) {
+ qDebug("Malformed block range");
+ return pr;
+ }
+
+ bool isBootBlock = false;
+ MemoryRangeType rtype = MemoryRangeType::Nb_Types;
+ Type ptype = Nb_Types;
+
+ for (MemoryRangeType type; type<=MemoryRangeType::Nb_Types; ++type) { // #### danger: <=
+ isBootBlock = ( type==MemoryRangeType::Nb_Types );
+ for (uint k=0; k<Nb_Types; k++) {
+ QString mname = (isBootBlock ? bootMaskName(Type(k)) : maskName(Type(k), type));
+ if ( rexp.cap(1)!=mname ) continue;
+ rtype = (isBootBlock ? MemoryRangeType(MemoryRangeType::Code) : type);
+ ptype = Type(k);
+ if ( !rexp.cap(2).isEmpty() ) {
+ if ( isBootBlock || (rtype!=MemoryRangeType::Code && rtype!=MemoryRangeType::Eeprom) ) {
+ qDebug("Multiple blocks only for code and eeprom");
+ return pr;
+ }
+ }
+ break;
+ }
+ if ( rtype!=MemoryRangeType::Nb_Types ) break;
+ }
+ if ( rtype==MemoryRangeType::Nb_Types ) {
+ qDebug("Unknown protected memory range");
+ return pr;
+ }
+
+ if ( isNoneProtectedValueName(name) ) {
+ ok = true;
+ return pr;
+ }
+
+ const Config::Mask *bmask = _config.findMask(bootMaskName(ptype));
+ const Config::Mask *bsmask = _config.findMask(bootSizeMaskName());
+ const MemoryRangeData &rdata = _data.range(rtype);
+ if ( isAllProtectedValueName(name) ) {
+ if ( rtype==MemoryRangeType::Code && !isBootBlock && bmask ) {
+ qDebug("Protected range should be explicit with boot block");
+ return pr;
+ }
+ if (isBootBlock) {
+ if ( bsmask==0 ) {
+ qDebug("Protected range should be explicit when boot size not present");
+ return pr;
+ }
+ Address start = _data.range(MemoryRangeType::Code).start;
+ pr.starts.append(start);
+ for (uint k=0; k<uint(bsmask->values.count()); k++) {
+ bool ok1;
+ uint size = bsmask->values[k].name.toUInt(&ok1);
+ if ( !ok1 ) {
+ qDebug("Could not recognize boot size value");
+ return pr;
+ }
+ if ( size==0 ) {
+ qDebug("Boot size cannot be zero");
+ return pr;
+ }
+ Address end = 2 * size - 1; // instruction words
+ if ( pr.ends.count()!=0 && end==pr.ends[pr.ends.count()-1] ) continue;
+ pr.ends.append(end);
+ qHeapSort(pr.ends);
+ }
+ } else {
+ pr.starts.append(rdata.start);
+ pr.ends.append(rdata.end);
+ }
+ ok = true;
+ return pr;
+ }
+ if ( isBootBlock && bsmask ) {
+ qDebug("Protected range should not be explicit when boot size is present");
+ return pr;
+ }
+
+ // extract start and end
+ Address end;
+ bool ok1;
+ if ( !extractRanges(name, pr.starts, end, ok1) ) {
+ qDebug("Could not recognized explicit range");
+ return pr;
+ }
+ if ( !ok1 ) return pr;
+ if ( end>rdata.end ) {
+ qDebug("End is beyond memory range");
+ return pr;
+ }
+ if ( (rtype!=MemoryRangeType::Code || isBootBlock) && (pr.starts.count()>1 || !rexp.cap(2).isEmpty() || bmask==0) ) {
+ qDebug("Only code with blocks and boot can have multiple protected ranges");
+ return pr;
+ }
+ if ( isBootBlock && pr.starts[0]!=0 ) {
+ qDebug("Boot block start should be zero");
+ return pr;
+ }
+ pr.ends.append(end);
+
+ // check with boot block
+ if ( pr.starts.count()>1 ) {
+ if ( bmask==0 ) {
+ qDebug("No boot mask");
+ return pr;
+ }
+ for (uint i=0; i<uint(bmask->values.count()); i++) {
+ if ( bmask->values[i].name=="Off" ) continue;
+ bool ok1;
+ ProtectedRange bpr = extractRange(bmask->name, bmask->values[i].name, ok1);
+ if ( !ok1 ) return pr;
+ if ( bpr.ends.count()!=pr.starts.count() ) {
+ qDebug("Boot number of ends (%i) should be the same as code number of starts (%i)", int(bpr.ends.count()), int(pr.starts.count()));
+ return pr;
+ }
+ for (uint k=0; k<uint(bpr.ends.count()); k++) {
+ if ( bpr.ends[k]+1!=pr.starts[k] ) {
+ qDebug("%i: End of boot block (%s) doesn't match start of code block (%s)", k, toHexLabelAbs(bpr.ends[k]).latin1(), toHexLabelAbs(pr.starts[k]).latin1());
+ return pr;
+ }
+ }
+ }
+ }
+
+ ok = true;
+ return pr;
+}
+
+bool Pic::Protection::hasBootBlock() const
+{
+ return ( _config.findMask("CPB") || _config.findMask(bootSizeMaskName()) );
+}
+
+uint Pic::Protection::nbBlocks() const
+{
+ if ( family()==CodeGuard ) return 2; // codeguard : secure segment + general segment
+ for (uint i=0; i<MAX_NB_BLOCKS; i++)
+ if ( _config.findMask(QString("CP_%1").arg(i))==0 ) return i;
+ return MAX_NB_BLOCKS;
+}
+
+QString Pic::Protection::bootLabel() const
+{
+ if ( family()==CodeGuard ) return i18n("Boot Segment");
+ return i18n("Boot Block");
+}
+
+QString Pic::Protection::blockLabel(uint i) const
+{
+ if ( family()==CodeGuard ) {
+ if ( i==0 ) return i18n("Secure Segment");
+ return i18n("General Segment");
+ }
+ return i18n("Block #%1").arg(i);
+}
diff --git a/src/devices/pic/base/pic_protection.h b/src/devices/pic/base/pic_protection.h
new file mode 100644
index 0000000..67ff667
--- /dev/null
+++ b/src/devices/pic/base/pic_protection.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+#ifndef PIC_PROTECTION_H
+#define PIC_PROTECTION_H
+
+#include "pic.h"
+
+namespace Pic
+{
+class Data;
+
+//----------------------------------------------------------------------------
+class Protection
+{
+public:
+ enum { MAX_NB_BLOCKS = 8 };
+ enum Family { NoProtection = 0, BasicProtection, BlockProtection, CodeGuard, Nb_Families };
+ enum Type { ProgramProtected = 0, WriteProtected, ReadProtected,
+ StandardSecurity, HighSecurity, Nb_Types };
+
+public:
+ Protection(const Pic::Data &data, const Config &config) : _data(data), _config(config) {}
+ Family family() const;
+ QString securityValueName(Type type) const;
+ bool hasBootBlock() const;
+ QString bootSizeMaskName() const;
+ QString bootMaskName(Type ptype) const;
+ QString bootLabel() const;
+ uint nbBlocks() const;
+ QString blockSizeMaskName(uint i) const;
+ QString blockMaskName(Type ptype, uint i) const;
+ QString blockLabel(uint i) const;
+ AddressRangeVector extractRanges(const QString &name, MemoryRangeType type) const;
+ bool checkRange(const QString &mask, const QString &name) const;
+ QString maskName(Type type, MemoryRangeType mtype) const;
+ bool isAllProtectedValueName(const QString &valueName) const;
+ bool isNoneProtectedValueName(const QString &valueName) const;
+
+private:
+ const Pic::Data &_data;
+ const Config &_config;
+
+ enum SegmentType { BootSegment = 0, SecureSegment, GeneralSegment, Nb_SegmentTypes };
+ static bool extractRanges(const QString &name, QValueVector<Address> &starts, Address &end, bool &ok);
+ class ProtectedRange {
+ public:
+ QValueVector<Address> starts, ends;
+ };
+ ProtectedRange extractRange(const QString &mask, const QString &name, bool &ok) const;
+};
+
+} //namespace
+
+#endif
diff --git a/src/devices/pic/base/pic_register.cpp b/src/devices/pic/base/pic_register.cpp
new file mode 100644
index 0000000..fcfe5ef
--- /dev/null
+++ b/src/devices/pic/base/pic_register.cpp
@@ -0,0 +1,287 @@
+/***************************************************************************
+ * Copyright (C) 2006 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 "pic_register.h"
+
+#include "pic.h"
+
+//-----------------------------------------------------------------------------
+Pic::RegistersData::RegistersData(const Data &data)
+ : nbBanks(0), accessBankSplit(0), _data(data)
+{}
+
+Address Pic::RegistersData::mirroredAddress(Address address) const
+{
+ Address mirror = address;
+ for (uint i=0; i<uint(mirrored.count()); i++) {
+ int delta = -1;
+ for (uint k=0; k<uint(mirrored[i].count()); k++) {
+ if ( address<mirrored[i][k].start
+ || address>=mirrored[i][k].start+mirrored[i][k].length ) continue;
+ delta = address - mirrored[i][k].start;
+ break;
+ }
+ if ( delta==-1 ) continue;
+ for (uint k=0; k<uint(mirrored[i].count()); k++)
+ mirror = QMIN(mirrored[i][k].start + delta, mirror);
+ break;
+ }
+ return mirror;
+}
+
+Device::RegisterProperties Pic::RegistersData::properties(Address address) const
+{
+ switch ( type(address) ) {
+ case Mirrored:
+ case UnusedRegister: return Device::NotAccessible;
+ case Gpr: return (Device::Readable | Device::Writable);
+ case Sfr: {
+ Device::RegisterProperties properties = Device::NotAccessible;
+ RegisterBitProperties rbp = RegisterBitUnused;
+ QMap<QString, RegisterData>::const_iterator it;
+ for (it=sfrs.begin(); it!=sfrs.end(); ++it) {
+ if ( it.data().address!=address ) continue;
+ for (uint i=0; i<Device::MAX_NB_PORT_BITS; i++) rbp |= it.data().bits[i].properties;
+ if ( rbp & RegisterBitRead ) properties |= Device::Readable;
+ if ( rbp & RegisterBitWrite ) properties |= Device::Writable;
+ break;
+ }
+ return properties;
+ }
+ }
+ Q_ASSERT(false);
+ return Device::NotAccessible;
+}
+
+Pic::RegisterType Pic::RegistersData::type(Address address) const
+{
+ for (uint i=0; i<uint(unused.count()); i++)
+ if ( address>=unused[i].start && address<unused[i].start+unused[i].length ) return UnusedRegister;
+ if ( !sfrNames[address].isEmpty() ) return Sfr;
+ Address mirror = mirroredAddress(address);
+ if ( !sfrNames[mirror].isEmpty() ) return Mirrored;
+ if ( address==mirror ) return Gpr;
+ return Mirrored;
+}
+
+QString Pic::RegistersData::label(Address address) const
+{
+ switch ( type(address) ) {
+ case UnusedRegister: return "---";
+ case Mirrored: return i18n("Mirror of %1").arg(toHexLabel(mirroredAddress(address), nbCharsAddress()));
+ case Gpr: return "<GPR>";
+ case Sfr: return sfrNames[address];
+ }
+ Q_ASSERT(false);
+ return QString::null;
+}
+
+bool Pic::RegistersData::hasPort(uint index) const
+{
+ Q_ASSERT( index<Device::MAX_NB_PORTS );
+ if ( sfrs.contains("GPIO") ) return ( index==0 );
+ if ( !sfrs.contains(portName(index)) ) return false;
+ return true;
+}
+
+int Pic::RegistersData::portIndex(Address address) const
+{
+ QString name = sfrNames[address];
+ if ( name.isEmpty() ) return -1;
+ for (uint i=0; i<Device::MAX_NB_PORTS; i++) {
+ if ( !hasPort(i) ) continue;
+ if ( name==portName(i) || name==trisName(i) || name==latchName(i) ) return i;
+ }
+ return -1;
+}
+
+bool Pic::RegistersData::hasPortBit(uint index, uint bit) const
+{
+ if ( !hasPort(index) ) return false;
+ const RegisterData &port = sfrs[portName(index)];
+ return ( port.bits[bit].properties!=RegisterBitUnused );
+}
+
+QString Pic::RegistersData::portName(uint index) const
+{
+ if ( sfrs.contains("GPIO") ) {
+ if ( index!=0 ) return QString::null;
+ return "GPIO";
+ }
+ return QString("PORT") + char('A' + index);
+}
+
+QString Pic::RegistersData::trisName(uint index) const
+{
+ if ( sfrs.contains("GPIO") ) {
+ if ( index!=0 ) return QString::null;
+ return "TRISIO";
+ }
+ if ( _data.architecture()==Architecture::P17C ) {
+ if ( index==0 ) return QString::null;
+ return QString("DDR") + char('A' + index);
+ }
+ return QString("TRIS") + char('A' + index);
+}
+
+bool Pic::RegistersData::hasTris(uint index) const
+{
+ QString name = trisName(index);
+ if ( name.isEmpty() ) return false;
+ return sfrs.contains(name);
+}
+
+QString Pic::RegistersData::latchName(uint index) const
+{
+ if ( _data.architecture()==Architecture::P10X || _data.architecture()==Architecture::P16X || _data.architecture()==Architecture::P17C )
+ return QString::null;
+ return QString("LAT") + char('A' + index);
+}
+
+bool Pic::RegistersData::hasLatch(uint index) const
+{
+ QString name = latchName(index);
+ if ( name.isEmpty() ) return false;
+ return sfrs.contains(name);
+}
+
+QString Pic::RegistersData::portBitName(uint index, uint bit) const
+{
+ if ( sfrs.contains("GPIO") ) return QString("GP") + QString::number(bit);
+ return QString("R") + char('A' + index) + QString::number(bit);
+}
+
+QValueList<Register::TypeData> Pic::RegistersData::relatedRegisters(const Register::TypeData &data) const
+{
+ QValueList<Register::TypeData> list;
+ if ( data.type()==Register::Regular ) {
+ int i = portIndex(data.address());
+ if ( i==-1 ) list.append(data);
+ else {
+ list.append(Register::TypeData(sfrs[portName(i)].address, nbChars()));
+ if ( hasTris(i) ) list.append(Register::TypeData(sfrs[trisName(i)].address, nbChars()));
+ if ( hasLatch(i) ) list.append(Register::TypeData(sfrs[latchName(i)].address, nbChars()));
+ }
+ } else if ( data.type()==Register::Combined ) {
+ uint nb = nbBitsToNbBytes(4*data.nbChars()) / nbBytes();
+ for (uint i=0; i<nb; i++) list.append(Register::TypeData(data.address() + i*nbBytes(), nbChars()));
+ } else list.append(data);
+ return list;
+}
+
+bool Pic::RegistersData::isBankUsed(uint i) const
+{
+ Q_ASSERT( i<nbBanks );
+ return !(unusedBankMask & (1 << i));
+}
+
+bool Pic::RegistersData::bankHasSfrs(uint i) const
+{
+ if ( i==0 ) return true;
+ if ( (_data.architecture()==Pic::Architecture::P18F || _data.architecture()==Pic::Architecture::P18J) && i==15 ) return true;
+ if ( !isBankUsed(i) ) return false;
+ QMap<Address, QString>::const_iterator it;
+ for (it=sfrNames.begin(); it!=sfrNames.end(); ++it)
+ if ( bankFromAddress(it.key())==i ) return true;
+ return false;
+}
+
+bool Pic::RegistersData::hasSharedGprs(uint &firstIndex, bool &all) const
+{
+ bool ok = false;
+ all = true;
+ for (uint i=0; i<nbRegistersPerBank(); i++) {
+ Address address = addressFromIndex(i);
+ if ( type(address)!=Gpr ) continue;
+ uint k = 1;
+ for (; k<nbBanks; k++) {
+ RegisterType t = type(address + k*nbBytesPerBank());
+ if ( t!=Mirrored ) break;
+ }
+ if ( k==nbBanks ) {
+ if ( !ok ) firstIndex = i;
+ ok = true;
+ } else all = false;
+ }
+ return ok;
+}
+
+uint Pic::RegistersData::firstGprIndex() const
+{
+ for (uint i=0; i<nbRegistersPerBank(); i++)
+ if ( type(addressFromIndex(i))==Gpr ) return i;
+ Q_ASSERT(false);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+QDataStream &Pic::operator <<(QDataStream &s, const RangeData &rd)
+{
+ s << rd.start << rd.length;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, RangeData &rd)
+{
+ s >> rd.start >> rd.length;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const RegisterBitData &rbd)
+{
+ s << Q_UINT8(rbd.properties) << Q_UINT8(rbd.por) << Q_UINT8(rbd.mclr);
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, RegisterBitData &rbd)
+{
+ Q_UINT8 properties, por, mclr;
+ s >> properties >> por >> mclr;
+ rbd.properties = RegisterBitProperties(properties);
+ rbd.por = RegisterBitState(por);
+ rbd.mclr = RegisterBitState(mclr);
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const RegisterData &rd)
+{
+ s << rd.address;
+ for (int i=0; i<Device::MAX_NB_PORT_BITS; i++) s << rd.bits[i];
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, RegisterData &rd)
+{
+ s >> rd.address;
+ for (int i=0; i<Device::MAX_NB_PORT_BITS; i++) s >> rd.bits[i];
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const CombinedData &rd)
+{
+ s << rd.address << rd.nbChars;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, CombinedData &rd)
+{
+ s >> rd.address >> rd.nbChars;
+ return s;
+}
+
+QDataStream &Pic::operator <<(QDataStream &s, const RegistersData &rd)
+{
+ s << rd.nbBanks << rd.accessBankSplit << rd.unusedBankMask;
+ s << rd.sfrs << rd.mirrored << rd.unused << rd.combined;
+ return s;
+}
+QDataStream &Pic::operator >>(QDataStream &s, RegistersData &rd)
+{
+ s >> rd.nbBanks >> rd.accessBankSplit >> rd.unusedBankMask;
+ s >> rd.sfrs >> rd.mirrored >> rd.unused >> rd.combined;
+ rd.sfrNames.clear();
+ QMap<QString, RegisterData>::const_iterator it;
+ for(it=rd.sfrs.begin(); it!=rd.sfrs.end(); ++it) rd.sfrNames[it.data().address] = it.key();
+ return s;
+}
diff --git a/src/devices/pic/base/pic_register.h b/src/devices/pic/base/pic_register.h
new file mode 100644
index 0000000..41da020
--- /dev/null
+++ b/src/devices/pic/base/pic_register.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * Copyright (C) 2006 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. *
+ ***************************************************************************/
+#ifndef PIC_REGISTER_H
+#define PIC_REGISTER_H
+
+#include <qmap.h>
+
+#include "devices/base/register.h"
+#include "pic.h"
+
+namespace Pic
+{
+class Data;
+struct RangeData {
+ Address start;
+ uint length;
+};
+
+//-----------------------------------------------------------------------------
+enum RegisterType { UnusedRegister, Sfr, Gpr, Mirrored};
+enum RegisterBitProperty { RegisterBitUnused = 0x0,
+ RegisterBitRead = 0x1, RegisterBitWrite = 0x2,
+ RegisterBitOnlySoftwareClear = 0x4, RegisterBitOnlySoftwareSet = 0x8,
+ MaxRegisterBitProperty = 0x15
+};
+Q_DECLARE_FLAGS(RegisterBitProperties, RegisterBitProperty)
+Q_DECLARE_OPERATORS_FOR_FLAGS(RegisterBitProperties)
+enum RegisterBitState { RegisterBitUnknown = 0, RegisterBitLow, RegisterBitHigh,
+ RegisterBitUnchanged, RegisterBitDepends, RegisterBitDependsConfig, Nb_RegisterBitStates
+};
+
+//-----------------------------------------------------------------------------
+class RegisterBitData
+{
+public:
+ RegisterBitData() : properties(RegisterBitUnused) {}
+ RegisterBitProperties properties;
+ RegisterBitState por, mclr;
+};
+struct RegisterData
+{
+ Address address;
+ RegisterBitData bits[Device::MAX_NB_PORT_BITS];
+};
+struct CombinedData
+{
+ Address address;
+ uint nbChars;
+};
+
+class RegistersData : public Device::RegistersData
+{
+public:
+ RegistersData(const Data &data);
+ virtual uint nbBits() const { return _data.architecture().data().nbBitsRegister; }
+ uint nbBytesPerBank() const { return _data.architecture().data().registerBankLength; }
+ uint nbRegistersPerBank() const { return nbBytesPerBank() / nbBytes(); }
+ uint nbCharsAddress() const { return ::nbChars(nbRegisters() - 1); }
+ virtual uint nbRegisters() const { return nbBanks * nbRegistersPerBank(); }
+ virtual uint addressFromIndex(uint i) const { return nbBytes() * i; }
+ virtual uint indexFromAddress(Address address) const { return address.toUInt() / nbBytes(); }
+ bool isBankUsed(uint i) const;
+ uint bankFromAddress(Address address) const { return indexFromAddress(address) / nbRegistersPerBank(); }
+ bool bankHasSfrs(uint i) const; // slow
+ bool hasSharedGprs(uint &firstIndex, bool &all) const; // i.e. mirrored in all banks (all is for first bank only)
+ uint firstGprIndex() const; // in first bank
+
+ uint nbBanks, accessBankSplit, unusedBankMask;
+ QMap<QString, RegisterData> sfrs;
+ QMap<Address, QString> sfrNames; // address -> name
+ QValueVector<QValueVector<RangeData> > mirrored;
+ QValueVector<RangeData> unused;
+ QMap<QString, CombinedData> combined;
+
+ virtual Device::RegisterProperties properties(Address address) const;
+ RegisterType type(Address address) const;
+ QString label(Address address) const;
+ virtual QValueList<Register::TypeData> relatedRegisters(const Register::TypeData &data) const;
+
+ virtual bool hasPort(uint index) const;
+ virtual int portIndex(Address address) const;
+ virtual QString portName(uint index) const;
+ bool hasTris(uint index) const;
+ QString trisName(uint index) const;
+ bool hasLatch(uint index) const;
+ QString latchName(uint index) const;
+ virtual bool hasPortBit(uint index, uint bit) const;
+ virtual QString portBitName(uint index, uint bit) const;
+
+private:
+ const Data &_data;
+ Address mirroredAddress(Address address) const;
+};
+
+//-----------------------------------------------------------------------------
+QDataStream &operator <<(QDataStream &s, const RangeData &rd);
+QDataStream &operator >>(QDataStream &s, RangeData &rd);
+QDataStream &operator <<(QDataStream &s, const RegisterBitData &rbd);
+QDataStream &operator >>(QDataStream &s, RegisterBitData &rbd);
+QDataStream &operator <<(QDataStream &s, const RegisterData &rd);
+QDataStream &operator >>(QDataStream &s, RegisterData &rd);
+QDataStream &operator <<(QDataStream &s, const CombinedData &rd);
+QDataStream &operator >>(QDataStream &s, CombinedData &rd);
+QDataStream &operator <<(QDataStream &s, const RegistersData &rd);
+QDataStream &operator >>(QDataStream &s, RegistersData &rd);
+
+} // namespace
+
+#endif