forked from qt-creator/qt-creator
BareMetal: Long live support for KEIL uVision v5.x debugger
This patch adds debugger integration from the KEIL uVision IDE: * http://www2.keil.com/mdk5/uvision/ This IDE has the uVision Socket Interface (UVSC) that allows to the applications configuration, building and debugging: * http://www.keil.com/appnotes/docs/apnt_198.asp Besides, it provides a binary client libraries for Windows, which are implements some API which we are use in this patch. Currently implemented the following features: * Enumeration of a stack frames. * Enumeration of a threads (tasks). * Registers view (read/write). * Local variables view (read/write). * Watchers view (read/write). * Disassembler view. * Current location marker. * Break-points. * Step-in. * Step-over. * Step-out. * Step-by-instruction. * Start/stop/pause/continue debugger. * Auto-detection for the installed uVision instances (as debuggers). * Wizard for choosing and configuring of the UVSC debug providers. At this moment added support only for the 32-bit ARM devices, provided by the STMicroelectronics: https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html For this are implemented two debugger providers: * Simulator - allow to simulate the target device. * ST-Link v2 - it is a HW debugger. This implementation tested only with the QBS using the following target boards: * NUCLEO-F767ZI (based on STM32F767ZIT6 MCU). * STM32F4DISCOVERY (based on STM32F407VG MCU). * STM32F103x (based on STM32F103C8T6 MCU). A more detailed information about this patch can be found in a bug-tracker. Fixes: QTCREATORBUG-23426 Change-Id: Ie36a1f7430b56c33d6665cc35e43fe9bd95d28f1 Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -19,6 +19,22 @@ add_qtc_plugin(BareMetal
|
||||
debugservers/gdb/stlinkutilgdbserverprovider.cpp debugservers/gdb/stlinkutilgdbserverprovider.h
|
||||
debugservers/gdb/jlinkgdbserverprovider.cpp debugservers/gdb/jlinkgdbserverprovider.h
|
||||
debugservers/gdb/eblinkgdbserverprovider.cpp debugservers/gdb/eblinkgdbserverprovider.h
|
||||
debugservers/uvsc/simulatoruvscserverprovider.cpp debugservers/uvsc/simulatoruvscserverprovider.h
|
||||
debugservers/uvsc/stlinkuvscserverprovider.cpp debugservers/uvsc/stlinkuvscserverprovider.h
|
||||
debugservers/uvsc/uvproject.cpp debugservers/uvsc/uvproject.h
|
||||
debugservers/uvsc/uvprojectwriter.cpp debugservers/uvsc/uvprojectwriter.h
|
||||
debugservers/uvsc/uvscserverprovider.cpp debugservers/uvsc/uvscserverprovider.h
|
||||
debugservers/uvsc/uvtargetdevicemodel.cpp debugservers/uvsc/uvtargetdevicemodel.h
|
||||
debugservers/uvsc/uvtargetdeviceselection.cpp debugservers/uvsc/uvtargetdeviceselection.h
|
||||
debugservers/uvsc/uvtargetdeviceviewer.cpp debugservers/uvsc/uvtargetdeviceviewer.h
|
||||
debugservers/uvsc/uvtargetdrivermodel.cpp debugservers/uvsc/uvtargetdrivermodel.h
|
||||
debugservers/uvsc/uvtargetdriverselection.cpp debugservers/uvsc/uvtargetdriverselection.h
|
||||
debugservers/uvsc/uvtargetdriverviewer.cpp debugservers/uvsc/uvtargetdriverviewer.h
|
||||
debugservers/uvsc/xmlnodevisitor.h
|
||||
debugservers/uvsc/xmlproject.cpp debugservers/uvsc/xmlproject.h
|
||||
debugservers/uvsc/xmlprojectwriter.cpp debugservers/uvsc/xmlprojectwriter.h
|
||||
debugservers/uvsc/xmlproperty.cpp debugservers/uvsc/xmlproperty.h
|
||||
debugservers/uvsc/xmlpropertygroup.cpp debugservers/uvsc/xmlpropertygroup.h
|
||||
iarewparser.cpp iarewparser.h
|
||||
iarewtoolchain.cpp iarewtoolchain.h
|
||||
idebugserverprovider.cpp idebugserverprovider.h
|
||||
|
||||
@@ -3,6 +3,8 @@ include(../../qtcreatorplugin.pri)
|
||||
|
||||
# GDB debug servers
|
||||
include(debugservers/gdb/gdbservers.pri)
|
||||
# UVSC debug servers
|
||||
include(debugservers/uvsc/uvscservers.pri)
|
||||
|
||||
# BareMetal files
|
||||
|
||||
|
||||
@@ -48,4 +48,27 @@ QtcPlugin {
|
||||
"eblinkgdbserverprovider.cpp", "eblinkgdbserverprovider.h",
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "UVSC Servers"
|
||||
prefix: "debugservers/uvsc/"
|
||||
files: [
|
||||
"simulatoruvscserverprovider.cpp", "simulatoruvscserverprovider.h",
|
||||
"stlinkuvscserverprovider.cpp", "stlinkuvscserverprovider.h",
|
||||
"uvproject.cpp", "uvproject.h",
|
||||
"uvprojectwriter.cpp", "uvprojectwriter.h",
|
||||
"uvscserverprovider.cpp", "uvscserverprovider.h",
|
||||
"uvtargetdevicemodel.cpp", "uvtargetdevicemodel.h",
|
||||
"uvtargetdeviceselection.cpp", "uvtargetdeviceselection.h",
|
||||
"uvtargetdeviceviewer.cpp", "uvtargetdeviceviewer.h",
|
||||
"uvtargetdrivermodel.cpp", "uvtargetdrivermodel.h",
|
||||
"uvtargetdriverselection.cpp", "uvtargetdriverselection.h",
|
||||
"uvtargetdriverviewer.cpp", "uvtargetdriverviewer.h",
|
||||
"xmlnodevisitor.h",
|
||||
"xmlproject.cpp", "xmlproject.h",
|
||||
"xmlprojectwriter.cpp", "xmlprojectwriter.h",
|
||||
"xmlproperty.cpp", "xmlproperty.h",
|
||||
"xmlpropertygroup.cpp", "xmlpropertygroup.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,16 @@ const char MENU_ID[] = "BareMetal.Menu";
|
||||
|
||||
const char DEBUG_SERVER_PROVIDERS_SETTINGS_ID[] = "EE.BareMetal.DebugServerProvidersOptions";
|
||||
|
||||
// Debugger Server Provider Ids
|
||||
// GDB Debugger Server Provider Ids.
|
||||
const char GDBSERVER_OPENOCD_PROVIDER_ID[] = "BareMetal.GdbServerProvider.OpenOcd";
|
||||
const char GDBSERVER_JLINK_PROVIDER_ID[] = "BareMetal.GdbServerProvider.JLink";
|
||||
const char GDBSERVER_STLINK_UTIL_PROVIDER_ID[] = "BareMetal.GdbServerProvider.STLinkUtil";
|
||||
const char GDBSERVER_EBLINK_PROVIDER_ID[] = "BareMetal.GdbServerProvider.EBlink";
|
||||
|
||||
// uVision Debugger Server Provider Ids.
|
||||
const char UVSC_SIMULATOR_PROVIDER_ID[] = "BareMetal.UvscServerProvider.Simulator";
|
||||
const char UVSC_STLINK_PROVIDER_ID[] = "BareMetal.UvscServerProvider.StLink";
|
||||
|
||||
// Toolchain types.
|
||||
const char IAREW_TOOLCHAIN_TYPEID[] = "BareMetal.ToolChain.Iar";
|
||||
const char KEIL_TOOLCHAIN_TYPEID[] = "BareMetal.ToolChain.Keil";
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include "debugserverprovidermanager.h"
|
||||
#include "idebugserverprovider.h"
|
||||
|
||||
#include "debugservers/gdb/gdbserverprovider.h"
|
||||
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
#include "debugservers/gdb/jlinkgdbserverprovider.h"
|
||||
#include "debugservers/gdb/eblinkgdbserverprovider.h"
|
||||
|
||||
// UVSC debug servers.
|
||||
#include "debugservers/uvsc/simulatoruvscserverprovider.h"
|
||||
#include "debugservers/uvsc/stlinkuvscserverprovider.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
@@ -59,7 +63,9 @@ DebugServerProviderManager::DebugServerProviderManager()
|
||||
, m_factories({new JLinkGdbServerProviderFactory,
|
||||
new OpenOcdGdbServerProviderFactory,
|
||||
new StLinkUtilGdbServerProviderFactory,
|
||||
new EBlinkGdbServerProviderFactory})
|
||||
new EBlinkGdbServerProviderFactory,
|
||||
new SimulatorUvscServerProviderFactory,
|
||||
new StLinkUvscServerProviderFactory})
|
||||
{
|
||||
m_instance = this;
|
||||
m_writer = new Utils::PersistentSettingsWriter(
|
||||
|
||||
@@ -72,6 +72,8 @@ static QString engineTypeName(DebuggerEngineType engineType)
|
||||
return DebugServerProviderModel::tr("Not recognized");
|
||||
case GdbEngineType:
|
||||
return DebugServerProviderModel::tr("GDB");
|
||||
case UvscEngineType:
|
||||
return DebugServerProviderModel::tr("UVSC");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
@@ -85,6 +87,9 @@ static QString engineTypeDescription(DebuggerEngineType engineType)
|
||||
case GdbEngineType:
|
||||
return DebugServerProviderModel::tr("GDB compatible provider engine\n" \
|
||||
"(used together with the GDB debuggers).");
|
||||
case UvscEngineType:
|
||||
return DebugServerProviderModel::tr("UVSC compatible provider engine\n" \
|
||||
"(used together with the KEIL uVision).");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "simulatoruvscserverprovider.h"
|
||||
|
||||
#include "uvproject.h"
|
||||
#include "uvprojectwriter.h"
|
||||
|
||||
#include <baremetal/baremetalconstants.h>
|
||||
#include <baremetal/baremetaldebugsupport.h>
|
||||
#include <baremetal/debugserverprovidermanager.h>
|
||||
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include <fstream> // for std::ofstream
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
using namespace Uv;
|
||||
|
||||
const char limitSpeedKeyC[] = "BareMetal.SimulatorUvscServerProvider.LimitSpeed";
|
||||
|
||||
static DriverSelection defaultSimulatorDriverSelection()
|
||||
{
|
||||
DriverSelection selection;
|
||||
// We don't use any driver DLL for a simulator,
|
||||
// we just use only one CPU DLL (yes?).
|
||||
selection.name = "None";
|
||||
selection.dll = "None";
|
||||
selection.index = 0;
|
||||
selection.cpuDlls = QStringList{"SARMCM3.DLL"};
|
||||
selection.cpuDllIndex = 0;
|
||||
return selection;
|
||||
}
|
||||
|
||||
// SimulatorUvProjectOptionsWriter
|
||||
|
||||
class SimulatorUvProjectOptions final : public Uv::ProjectOptions
|
||||
{
|
||||
public:
|
||||
explicit SimulatorUvProjectOptions(const SimulatorUvscServerProvider *provider)
|
||||
: Uv::ProjectOptions(provider)
|
||||
{
|
||||
m_debugOpt->appendProperty("sLrtime", int(provider->m_limitSpeed));
|
||||
}
|
||||
};
|
||||
|
||||
// SimulatorUvscServerProvider
|
||||
|
||||
SimulatorUvscServerProvider::SimulatorUvscServerProvider()
|
||||
: UvscServerProvider(Constants::UVSC_SIMULATOR_PROVIDER_ID)
|
||||
{
|
||||
setTypeDisplayName(tr("uVision Simulator"));
|
||||
setConfigurationWidgetCreator([this] { return new SimulatorUvscServerProviderConfigWidget(this); });
|
||||
setDriverSelection(defaultSimulatorDriverSelection());
|
||||
}
|
||||
|
||||
QVariantMap SimulatorUvscServerProvider::toMap() const
|
||||
{
|
||||
QVariantMap data = UvscServerProvider::toMap();
|
||||
data.insert(limitSpeedKeyC, m_limitSpeed);
|
||||
return data;
|
||||
}
|
||||
|
||||
bool SimulatorUvscServerProvider::fromMap(const QVariantMap &data)
|
||||
{
|
||||
if (!UvscServerProvider::fromMap(data))
|
||||
return false;
|
||||
m_limitSpeed = data.value(limitSpeedKeyC).toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimulatorUvscServerProvider::operator==(const IDebugServerProvider &other) const
|
||||
{
|
||||
if (!UvscServerProvider::operator==(other))
|
||||
return false;
|
||||
const auto p = static_cast<const SimulatorUvscServerProvider *>(&other);
|
||||
return m_limitSpeed == p->m_limitSpeed;
|
||||
}
|
||||
|
||||
FilePath SimulatorUvscServerProvider::optionsFilePath(DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const
|
||||
{
|
||||
const FilePath optionsPath = buildOptionsFilePath(runTool);
|
||||
std::ofstream ofs(optionsPath.toString().toStdString(), std::ofstream::out);
|
||||
Uv::ProjectOptionsWriter writer(&ofs);
|
||||
const SimulatorUvProjectOptions projectOptions(this);
|
||||
if (!writer.write(&projectOptions)) {
|
||||
errorMessage = BareMetalDebugSupport::tr(
|
||||
"Unable to create an uVision project options template");
|
||||
return {};
|
||||
}
|
||||
return optionsPath;
|
||||
}
|
||||
|
||||
// SimulatorUvscServerProviderFactory
|
||||
|
||||
SimulatorUvscServerProviderFactory::SimulatorUvscServerProviderFactory()
|
||||
{
|
||||
setId(Constants::UVSC_SIMULATOR_PROVIDER_ID);
|
||||
setDisplayName(UvscServerProvider::tr("uVision Simulator"));
|
||||
setCreator([] { return new SimulatorUvscServerProvider; });
|
||||
}
|
||||
|
||||
// SimulatorUvscServerProviderConfigWidget
|
||||
|
||||
SimulatorUvscServerProviderConfigWidget::SimulatorUvscServerProviderConfigWidget(
|
||||
SimulatorUvscServerProvider *p)
|
||||
: UvscServerProviderConfigWidget(p)
|
||||
{
|
||||
Q_ASSERT(p);
|
||||
|
||||
m_limitSpeedCheckBox = new QCheckBox;
|
||||
m_limitSpeedCheckBox->setToolTip(tr("Limit speed to real-time"));
|
||||
m_mainLayout->addRow(tr("Limit speed to real-time:"), m_limitSpeedCheckBox);
|
||||
|
||||
setFromProvider();
|
||||
|
||||
connect(m_limitSpeedCheckBox, &QAbstractButton::clicked,
|
||||
this, &SimulatorUvscServerProviderConfigWidget::dirty);
|
||||
}
|
||||
|
||||
void SimulatorUvscServerProviderConfigWidget::apply()
|
||||
{
|
||||
const auto p = static_cast<SimulatorUvscServerProvider *>(m_provider);
|
||||
Q_ASSERT(p);
|
||||
p->m_limitSpeed = m_limitSpeedCheckBox->isChecked();
|
||||
UvscServerProviderConfigWidget::apply();
|
||||
}
|
||||
|
||||
void SimulatorUvscServerProviderConfigWidget::discard()
|
||||
{
|
||||
setFromProvider();
|
||||
UvscServerProviderConfigWidget::discard();
|
||||
}
|
||||
|
||||
void SimulatorUvscServerProviderConfigWidget::setFromProvider()
|
||||
{
|
||||
const auto p = static_cast<SimulatorUvscServerProvider *>(m_provider);
|
||||
Q_ASSERT(p);
|
||||
const QSignalBlocker blocker(this);
|
||||
m_limitSpeedCheckBox->setChecked(p->m_limitSpeed);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvscserverprovider.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QCheckBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
// SimulatorUvscServerProvider
|
||||
|
||||
class SimulatorUvscServerProvider final : public UvscServerProvider
|
||||
{
|
||||
public:
|
||||
QVariantMap toMap() const final;
|
||||
bool fromMap(const QVariantMap &data) final;
|
||||
|
||||
bool operator==(const IDebugServerProvider &other) const final;
|
||||
bool isSimulator() const final { return true; }
|
||||
|
||||
Utils::FilePath optionsFilePath(Debugger::DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const final;
|
||||
|
||||
private:
|
||||
explicit SimulatorUvscServerProvider();
|
||||
|
||||
bool m_limitSpeed = false;
|
||||
|
||||
friend class SimulatorUvscServerProviderConfigWidget;
|
||||
friend class SimulatorUvscServerProviderFactory;
|
||||
friend class SimulatorUvProjectOptions;
|
||||
};
|
||||
|
||||
// SimulatorUvscServerProviderFactory
|
||||
|
||||
class SimulatorUvscServerProviderFactory final : public IDebugServerProviderFactory
|
||||
{
|
||||
public:
|
||||
SimulatorUvscServerProviderFactory();
|
||||
};
|
||||
|
||||
// SimulatorUvscServerProviderConfigWidget
|
||||
|
||||
class SimulatorUvscServerProviderConfigWidget final : public UvscServerProviderConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SimulatorUvscServerProviderConfigWidget(SimulatorUvscServerProvider *provider);
|
||||
|
||||
private:
|
||||
void apply() override;
|
||||
void discard() override;
|
||||
|
||||
void setFromProvider();
|
||||
|
||||
QCheckBox *m_limitSpeedCheckBox = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,348 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "stlinkuvscserverprovider.h"
|
||||
|
||||
#include "uvproject.h"
|
||||
#include "uvprojectwriter.h"
|
||||
|
||||
#include <baremetal/baremetalconstants.h>
|
||||
#include <baremetal/baremetaldebugsupport.h>
|
||||
#include <baremetal/debugserverprovidermanager.h>
|
||||
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFileInfo>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include <fstream> // for std::ofstream
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
using namespace Uv;
|
||||
|
||||
constexpr char adapterOptionsKeyC[] = "BareMetal.StLinkUvscServerProvider.AdapterOptions";
|
||||
constexpr char adapterPortKeyC[] = "BareMetal.StLinkUvscServerProvider.AdapterPort";
|
||||
constexpr char adapterSpeedKeyC[] = "BareMetal.StLinkUvscServerProvider.AdapterSpeed";
|
||||
|
||||
static QString buildAdapterOptions(const StLinkUvscAdapterOptions &opts)
|
||||
{
|
||||
QString s;
|
||||
if (opts.port == StLinkUvscAdapterOptions::JTAG)
|
||||
s += "-0142";
|
||||
else if (opts.port == StLinkUvscAdapterOptions::SWD)
|
||||
s += "-0206";
|
||||
|
||||
s += " -S" + QString::number(opts.speed);
|
||||
return s;
|
||||
}
|
||||
|
||||
static QString buildDllRegistryKey(const DriverSelection &driver)
|
||||
{
|
||||
const QFileInfo fi(driver.dll);
|
||||
return fi.baseName();
|
||||
}
|
||||
|
||||
static QString buildDllRegistryName(const DeviceSelection &device,
|
||||
const StLinkUvscAdapterOptions &opts)
|
||||
{
|
||||
if (device.algorithmIndex < 0 || device.algorithmIndex >= int(device.algorithms.size()))
|
||||
return {};
|
||||
const DeviceSelection::Algorithm algorithm = device.algorithms.at(device.algorithmIndex);
|
||||
const QFileInfo path(algorithm.path);
|
||||
const QString start = algorithm.start.startsWith("0x") ? algorithm.start.mid(2)
|
||||
: algorithm.start;
|
||||
const QString size = algorithm.size.startsWith("0x") ? algorithm.size.mid(2)
|
||||
: algorithm.size;
|
||||
const QString adaptOpts = buildAdapterOptions(opts);
|
||||
return QStringLiteral(" %6 -FN1 -FF0%1 -FS0%2 -FL0%3 -FP0($$Device:%4$%5)")
|
||||
.arg(path.fileName(), start, size, device.name, path.filePath(), adaptOpts);
|
||||
}
|
||||
|
||||
// StLinkUvProjectOptions
|
||||
|
||||
class StLinkUvProjectOptions final : public Uv::ProjectOptions
|
||||
{
|
||||
public:
|
||||
explicit StLinkUvProjectOptions(const StLinkUvscServerProvider *provider)
|
||||
: Uv::ProjectOptions(provider)
|
||||
{
|
||||
const DriverSelection driver = provider->driverSelection();
|
||||
const DeviceSelection device = provider->deviceSelection();
|
||||
m_debugOpt->appendProperty("nTsel", driver.index);
|
||||
m_debugOpt->appendProperty("pMon", driver.dll);
|
||||
|
||||
// Fill 'TargetDriverDllRegistry' (required for dedugging).
|
||||
const auto dllRegistry = m_targetOption->appendPropertyGroup("TargetDriverDllRegistry");
|
||||
const auto setRegEntry = dllRegistry->appendPropertyGroup("SetRegEntry");
|
||||
setRegEntry->appendProperty("Number", 0);
|
||||
const QString key = buildDllRegistryKey(driver);
|
||||
setRegEntry->appendProperty("Key", key);
|
||||
const QString name = buildDllRegistryName(device, provider->m_adapterOpts);
|
||||
setRegEntry->appendProperty("Name", name);
|
||||
}
|
||||
};
|
||||
|
||||
// StLinkUvscAdapterOptions
|
||||
|
||||
QVariantMap StLinkUvscAdapterOptions::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(adapterPortKeyC, port);
|
||||
map.insert(adapterSpeedKeyC, speed);
|
||||
return map;
|
||||
}
|
||||
|
||||
bool StLinkUvscAdapterOptions::fromMap(const QVariantMap &data)
|
||||
{
|
||||
port = static_cast<Port>(data.value(adapterPortKeyC, SWD).toInt());
|
||||
speed = static_cast<Speed>(data.value(adapterSpeedKeyC, Speed_4MHz).toInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StLinkUvscAdapterOptions::operator==(const StLinkUvscAdapterOptions &other) const
|
||||
{
|
||||
return port == other.port && speed == other.speed;
|
||||
}
|
||||
|
||||
// StLinkUvscServerProvider
|
||||
|
||||
StLinkUvscServerProvider::StLinkUvscServerProvider()
|
||||
: UvscServerProvider(Constants::UVSC_STLINK_PROVIDER_ID)
|
||||
{
|
||||
setTypeDisplayName(tr("uVision St-Link"));
|
||||
setConfigurationWidgetCreator([this] { return new StLinkUvscServerProviderConfigWidget(this); });
|
||||
setSupportedDrivers({"STLink\\ST-LINKIII-KEIL_SWO.dll"});
|
||||
}
|
||||
|
||||
QVariantMap StLinkUvscServerProvider::toMap() const
|
||||
{
|
||||
QVariantMap data = UvscServerProvider::toMap();
|
||||
data.insert(adapterOptionsKeyC, m_adapterOpts.toMap());
|
||||
return data;
|
||||
}
|
||||
|
||||
bool StLinkUvscServerProvider::fromMap(const QVariantMap &data)
|
||||
{
|
||||
if (!UvscServerProvider::fromMap(data))
|
||||
return false;
|
||||
m_adapterOpts.fromMap(data.value(adapterOptionsKeyC).toMap());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StLinkUvscServerProvider::operator==(const IDebugServerProvider &other) const
|
||||
{
|
||||
if (!UvscServerProvider::operator==(other))
|
||||
return false;
|
||||
const auto p = static_cast<const StLinkUvscServerProvider *>(&other);
|
||||
return m_adapterOpts == p->m_adapterOpts;
|
||||
return true;
|
||||
}
|
||||
|
||||
FilePath StLinkUvscServerProvider::optionsFilePath(DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const
|
||||
{
|
||||
const FilePath optionsPath = buildOptionsFilePath(runTool);
|
||||
std::ofstream ofs(optionsPath.toString().toStdString(), std::ofstream::out);
|
||||
Uv::ProjectOptionsWriter writer(&ofs);
|
||||
const StLinkUvProjectOptions projectOptions(this);
|
||||
if (!writer.write(&projectOptions)) {
|
||||
errorMessage = BareMetalDebugSupport::tr(
|
||||
"Unable to create an uVision project options template");
|
||||
return {};
|
||||
}
|
||||
return optionsPath;
|
||||
}
|
||||
|
||||
// StLinkUvscServerProviderFactory
|
||||
|
||||
StLinkUvscServerProviderFactory::StLinkUvscServerProviderFactory()
|
||||
{
|
||||
setId(Constants::UVSC_STLINK_PROVIDER_ID);
|
||||
setDisplayName(UvscServerProvider::tr("uVision St-Link"));
|
||||
setCreator([] { return new StLinkUvscServerProvider; });
|
||||
}
|
||||
|
||||
// StLinkUvscServerProviderConfigWidget
|
||||
|
||||
StLinkUvscServerProviderConfigWidget::StLinkUvscServerProviderConfigWidget(
|
||||
StLinkUvscServerProvider *p)
|
||||
: UvscServerProviderConfigWidget(p)
|
||||
{
|
||||
Q_ASSERT(p);
|
||||
|
||||
m_adapterOptionsWidget = new StLinkUvscAdapterOptionsWidget;
|
||||
m_mainLayout->addRow(tr("Adapter options:"), m_adapterOptionsWidget);
|
||||
|
||||
setFromProvider();
|
||||
|
||||
connect(m_adapterOptionsWidget, &StLinkUvscAdapterOptionsWidget::optionsChanged,
|
||||
this, &StLinkUvscServerProviderConfigWidget::dirty);
|
||||
}
|
||||
|
||||
void StLinkUvscServerProviderConfigWidget::apply()
|
||||
{
|
||||
const auto p = static_cast<StLinkUvscServerProvider *>(m_provider);
|
||||
Q_ASSERT(p);
|
||||
p->m_adapterOpts = adapterOptions();
|
||||
UvscServerProviderConfigWidget::apply();
|
||||
}
|
||||
|
||||
void StLinkUvscServerProviderConfigWidget::discard()
|
||||
{
|
||||
setFromProvider();
|
||||
UvscServerProviderConfigWidget::discard();
|
||||
}
|
||||
|
||||
void StLinkUvscServerProviderConfigWidget::setAdapterOpitons(
|
||||
const StLinkUvscAdapterOptions &adapterOpts)
|
||||
{
|
||||
m_adapterOptionsWidget->setAdapterOptions(adapterOpts);
|
||||
}
|
||||
|
||||
StLinkUvscAdapterOptions StLinkUvscServerProviderConfigWidget::adapterOptions() const
|
||||
{
|
||||
return m_adapterOptionsWidget->adapterOptions();
|
||||
}
|
||||
|
||||
void StLinkUvscServerProviderConfigWidget::setFromProvider()
|
||||
{
|
||||
const auto p = static_cast<StLinkUvscServerProvider *>(m_provider);
|
||||
Q_ASSERT(p);
|
||||
const QSignalBlocker blocker(this);
|
||||
setAdapterOpitons(p->m_adapterOpts);
|
||||
}
|
||||
|
||||
// StLinkUvscAdapterOptionsWidget
|
||||
|
||||
StLinkUvscAdapterOptionsWidget::StLinkUvscAdapterOptionsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
const auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(new QLabel(tr("Port:")));
|
||||
m_portBox = new QComboBox;
|
||||
layout->addWidget(m_portBox);
|
||||
layout->addWidget(new QLabel(tr("Speed:")));
|
||||
m_speedBox = new QComboBox;
|
||||
layout->addWidget(m_speedBox);
|
||||
setLayout(layout);
|
||||
|
||||
populatePorts();
|
||||
|
||||
connect(m_portBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, [this](int index) {
|
||||
Q_UNUSED(index);
|
||||
populateSpeeds();
|
||||
emit optionsChanged();
|
||||
});
|
||||
connect(m_speedBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &StLinkUvscAdapterOptionsWidget::optionsChanged);
|
||||
}
|
||||
|
||||
void StLinkUvscAdapterOptionsWidget::setAdapterOptions(
|
||||
const StLinkUvscAdapterOptions &adapterOpts)
|
||||
{
|
||||
for (auto index = 0; m_portBox->count(); ++index) {
|
||||
const StLinkUvscAdapterOptions::Port port = portAt(index);
|
||||
if (port == adapterOpts.port) {
|
||||
m_portBox->setCurrentIndex(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
populateSpeeds();
|
||||
|
||||
for (auto index = 0; m_speedBox->count(); ++index) {
|
||||
const StLinkUvscAdapterOptions::Speed speed = speedAt(index);
|
||||
if (speed == adapterOpts.speed) {
|
||||
m_speedBox->setCurrentIndex(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StLinkUvscAdapterOptions StLinkUvscAdapterOptionsWidget::adapterOptions() const
|
||||
{
|
||||
const auto port = portAt(m_portBox->currentIndex());
|
||||
const auto speed = speedAt(m_speedBox->currentIndex());
|
||||
return {port, speed};
|
||||
}
|
||||
|
||||
StLinkUvscAdapterOptions::Port StLinkUvscAdapterOptionsWidget::portAt(int index) const
|
||||
{
|
||||
return static_cast<StLinkUvscAdapterOptions::Port>(m_portBox->itemData(index).toInt());
|
||||
}
|
||||
|
||||
StLinkUvscAdapterOptions::Speed StLinkUvscAdapterOptionsWidget::speedAt(int index) const
|
||||
{
|
||||
return static_cast<StLinkUvscAdapterOptions::Speed>(m_speedBox->itemData(index).toInt());
|
||||
}
|
||||
|
||||
void StLinkUvscAdapterOptionsWidget::populatePorts()
|
||||
{
|
||||
m_portBox->addItem(tr("JTAG"), StLinkUvscAdapterOptions::JTAG);
|
||||
m_portBox->addItem(tr("SWD"), StLinkUvscAdapterOptions::SWD);
|
||||
}
|
||||
|
||||
void StLinkUvscAdapterOptionsWidget::populateSpeeds()
|
||||
{
|
||||
m_speedBox->clear();
|
||||
|
||||
const auto port = portAt(m_portBox->currentIndex());
|
||||
if (port == StLinkUvscAdapterOptions::JTAG) {
|
||||
m_speedBox->addItem(tr("9MHz"), StLinkUvscAdapterOptions::Speed_9MHz);
|
||||
m_speedBox->addItem(tr("4.5MHz"), StLinkUvscAdapterOptions::Speed_4_5MHz);
|
||||
m_speedBox->addItem(tr("2.25MHz"), StLinkUvscAdapterOptions::Speed_2_25MHz);
|
||||
m_speedBox->addItem(tr("1.12MHz"), StLinkUvscAdapterOptions::Speed_1_12MHz);
|
||||
m_speedBox->addItem(tr("560kHz"), StLinkUvscAdapterOptions::Speed_560kHz);
|
||||
m_speedBox->addItem(tr("280kHz"), StLinkUvscAdapterOptions::Speed_280kHz);
|
||||
m_speedBox->addItem(tr("140kHz"), StLinkUvscAdapterOptions::Speed_140kHz);
|
||||
} else if (port == StLinkUvscAdapterOptions::SWD) {
|
||||
m_speedBox->addItem(tr("4MHz"), StLinkUvscAdapterOptions::Speed_4MHz);
|
||||
m_speedBox->addItem(tr("1.8MHz"), StLinkUvscAdapterOptions::Speed_1_8MHz);
|
||||
m_speedBox->addItem(tr("950kHz"), StLinkUvscAdapterOptions::Speed_950kHz);
|
||||
m_speedBox->addItem(tr("480kHz"), StLinkUvscAdapterOptions::Speed_480kHz);
|
||||
m_speedBox->addItem(tr("240kHz"), StLinkUvscAdapterOptions::Speed_240kHz);
|
||||
m_speedBox->addItem(tr("125kHz"), StLinkUvscAdapterOptions::Speed_125kHz);
|
||||
m_speedBox->addItem(tr("100kHz"), StLinkUvscAdapterOptions::Speed_100kHz);
|
||||
m_speedBox->addItem(tr("50kHz"), StLinkUvscAdapterOptions::Speed_50kHz);
|
||||
m_speedBox->addItem(tr("25kHz"), StLinkUvscAdapterOptions::Speed_25kHz);
|
||||
m_speedBox->addItem(tr("15kHz"), StLinkUvscAdapterOptions::Speed_15kHz);
|
||||
m_speedBox->addItem(tr("5kHz"), StLinkUvscAdapterOptions::Speed_5kHz);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,136 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvscserverprovider.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
// StLinkUvscAdapterOptions
|
||||
|
||||
class StLinkUvscAdapterOptions final
|
||||
{
|
||||
public:
|
||||
enum Port { JTAG, SWD };
|
||||
enum Speed {
|
||||
// SWD speeds.
|
||||
Speed_4MHz = 0, Speed_1_8MHz, Speed_950kHz, Speed_480kHz,
|
||||
Speed_240kHz, Speed_125kHz, Speed_100kHz, Speed_50kHz,
|
||||
Speed_25kHz, Speed_15kHz, Speed_5kHz,
|
||||
// JTAG speeds.
|
||||
Speed_9MHz = 256, Speed_4_5MHz, Speed_2_25MHz, Speed_1_12MHz,
|
||||
Speed_560kHz, Speed_280kHz, Speed_140kHz,
|
||||
};
|
||||
Port port = Port::SWD;
|
||||
Speed speed = Speed::Speed_4MHz;
|
||||
|
||||
QVariantMap toMap() const;
|
||||
bool fromMap(const QVariantMap &data);
|
||||
bool operator==(const StLinkUvscAdapterOptions &other) const;
|
||||
};
|
||||
|
||||
// StLinkUvscServerProvider
|
||||
|
||||
class StLinkUvscServerProvider final : public UvscServerProvider
|
||||
{
|
||||
public:
|
||||
QVariantMap toMap() const final;
|
||||
bool fromMap(const QVariantMap &data) final;
|
||||
|
||||
bool operator==(const IDebugServerProvider &other) const final;
|
||||
Utils::FilePath optionsFilePath(Debugger::DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const final;
|
||||
private:
|
||||
explicit StLinkUvscServerProvider();
|
||||
|
||||
StLinkUvscAdapterOptions m_adapterOpts;
|
||||
|
||||
friend class StLinkUvscServerProviderConfigWidget;
|
||||
friend class StLinkUvscServerProviderFactory;
|
||||
friend class StLinkUvProjectOptions;
|
||||
};
|
||||
|
||||
// StLinkUvscServerProviderFactory
|
||||
|
||||
class StLinkUvscServerProviderFactory final : public IDebugServerProviderFactory
|
||||
{
|
||||
public:
|
||||
StLinkUvscServerProviderFactory();
|
||||
};
|
||||
|
||||
// StLinkUvscServerProviderConfigWidget
|
||||
|
||||
class StLinkUvscAdapterOptionsWidget;
|
||||
class StLinkUvscServerProviderConfigWidget final : public UvscServerProviderConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StLinkUvscServerProviderConfigWidget(StLinkUvscServerProvider *provider);
|
||||
|
||||
private:
|
||||
void apply() override;
|
||||
void discard() override;
|
||||
|
||||
void setAdapterOpitons(const StLinkUvscAdapterOptions &adapterOpts);
|
||||
StLinkUvscAdapterOptions adapterOptions() const;
|
||||
void setFromProvider();
|
||||
|
||||
StLinkUvscAdapterOptionsWidget *m_adapterOptionsWidget = nullptr;
|
||||
};
|
||||
|
||||
// StLinkUvscAdapterOptionsWidget
|
||||
|
||||
class StLinkUvscAdapterOptionsWidget final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StLinkUvscAdapterOptionsWidget(QWidget *parent = nullptr);
|
||||
void setAdapterOptions(const StLinkUvscAdapterOptions &adapterOpts);
|
||||
StLinkUvscAdapterOptions adapterOptions() const;
|
||||
|
||||
signals:
|
||||
void optionsChanged();
|
||||
|
||||
private:
|
||||
StLinkUvscAdapterOptions::Port portAt(int index) const;
|
||||
StLinkUvscAdapterOptions::Speed speedAt(int index) const;
|
||||
|
||||
void populatePorts();
|
||||
void populateSpeeds();
|
||||
|
||||
QComboBox *m_portBox = nullptr;
|
||||
QComboBox *m_speedBox = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,288 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h"
|
||||
#include "uvscserverprovider.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
#include <debugger/debuggerruncontrol.h>
|
||||
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
using namespace CppTools;
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
const char kProjectSchema[] = "2.1";
|
||||
|
||||
// Helpers
|
||||
|
||||
QString toolsFilePath(const QString &uVisionFilePath)
|
||||
{
|
||||
const QFileInfo fi(uVisionFilePath);
|
||||
QDir dir = fi.dir();
|
||||
if (!dir.cdUp())
|
||||
return {};
|
||||
return dir.absoluteFilePath("tools.ini");
|
||||
}
|
||||
|
||||
QString targetUVisionPath()
|
||||
{
|
||||
if (const Target *target = SessionManager::startupTarget()) {
|
||||
if (const Kit *kit = target->kit()) {
|
||||
const Runnable runnable = DebuggerKitAspect::runnable(kit);
|
||||
return runnable.executable.toString();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static QString buildToolsetNumber(int number)
|
||||
{
|
||||
return QStringLiteral("0x%1").arg(QString::number(number, 16));
|
||||
}
|
||||
|
||||
static QString buildVendor(const QString &vendor)
|
||||
{
|
||||
// Remove the colon symbol.
|
||||
const int colonIndex = vendor.lastIndexOf(':');
|
||||
return vendor.mid(0, colonIndex);
|
||||
}
|
||||
|
||||
static QString buildPackageId(const DeviceSelection::Package &package)
|
||||
{
|
||||
return QStringLiteral("%1.%2.%3").arg(package.vendor, package.name, package.version);
|
||||
}
|
||||
|
||||
static QString buildCpu(const DeviceSelection &device)
|
||||
{
|
||||
QString cpu;
|
||||
for (const DeviceSelection::Memory &memory : device.memories) {
|
||||
const QString id = (memory.id == "IRAM1")
|
||||
? "IRAM" : ((memory.id == "IROM1") ? "IROM" : memory.id);
|
||||
cpu += id + '(' + memory.start + ',' + memory.size + ") ";
|
||||
}
|
||||
cpu += "CPUTYPE(\"" + device.cpu.core + "\")";
|
||||
return cpu;
|
||||
}
|
||||
|
||||
static QString buildCpuDllName(const DriverSelection &driver)
|
||||
{
|
||||
if (driver.cpuDllIndex < 0 || driver.cpuDllIndex >= driver.cpuDlls.count())
|
||||
return {};
|
||||
return driver.cpuDlls.at(driver.cpuDllIndex);
|
||||
}
|
||||
|
||||
static QString buildCpuDllParameters(bool isSimulator)
|
||||
{
|
||||
QString params = " -MPU";
|
||||
if (isSimulator)
|
||||
params.prepend(" -REMAP");
|
||||
return params;
|
||||
}
|
||||
|
||||
static void extractAllFiles(const DebuggerRunTool *runTool, QStringList &includes,
|
||||
FilePaths &headers, FilePaths &sources, FilePaths &assemblers)
|
||||
{
|
||||
const auto project = runTool->runControl()->project();
|
||||
const CppTools::ProjectInfo info = CppModelManager::instance()->projectInfo(project);
|
||||
const QVector<ProjectPart::Ptr> parts = info.projectParts();
|
||||
for (const ProjectPart::Ptr &part : parts) {
|
||||
for (const ProjectFile &file : part->files) {
|
||||
if (!file.active)
|
||||
continue;
|
||||
const auto path = FilePath::fromString(file.path);
|
||||
if (file.isHeader() && !headers.contains(path))
|
||||
headers.push_back(path);
|
||||
else if (file.isSource() && !sources.contains(path))
|
||||
sources.push_back(path);
|
||||
else if (file.path.endsWith(".s") && !assemblers.contains(path))
|
||||
assemblers.push_back(path);
|
||||
}
|
||||
for (const HeaderPath &include : part->headerPaths) {
|
||||
if (!includes.contains(include.path))
|
||||
includes.push_back(include.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Project
|
||||
|
||||
Project::Project(const UvscServerProvider *provider, DebuggerRunTool *runTool)
|
||||
{
|
||||
appendProperty("SchemaVersion", kProjectSchema);
|
||||
appendProperty("Header", "### uVision Project, generated by QtCreator");
|
||||
|
||||
const auto targets = appendChild<Gen::Xml::PropertyGroup>("Targets");
|
||||
// Fill 'Target' group.
|
||||
m_target = targets->appendPropertyGroup("Target");
|
||||
m_target->appendProperty("TargetName", "Template");
|
||||
const int toolsetNo = provider->toolsetNumber();
|
||||
const QString toolsetNumber = buildToolsetNumber(toolsetNo);
|
||||
m_target->appendProperty("ToolsetNumber", toolsetNumber);
|
||||
// Fill 'TargetOption' group.
|
||||
const auto targetOption = m_target->appendPropertyGroup("TargetOption");
|
||||
|
||||
// Fill 'TargetCommonOption' group.
|
||||
const auto targetCommonOption = targetOption->appendPropertyGroup("TargetCommonOption");
|
||||
const DeviceSelection device = provider->deviceSelection();
|
||||
targetCommonOption->appendProperty("Device", device.name);
|
||||
const QString vendor = buildVendor(device.vendor);
|
||||
targetCommonOption->appendProperty("Vendor", vendor);
|
||||
const QString packageId = buildPackageId(device.package);
|
||||
targetCommonOption->appendProperty("PackID", packageId);
|
||||
targetCommonOption->appendProperty("PackURL", device.package.url);
|
||||
const QString cpu = buildCpu(device);
|
||||
targetCommonOption->appendProperty("Cpu", cpu);
|
||||
|
||||
// Fill 'DllOption' group (required for debugging).
|
||||
const auto dllOption = targetOption->appendPropertyGroup("DllOption");
|
||||
const DriverSelection driver = provider->driverSelection();
|
||||
|
||||
const QString cpuDllName = buildCpuDllName(driver);
|
||||
const QString simulatorCpuDllParameters = buildCpuDllParameters(true);
|
||||
const QString targetCpuDllParameters = buildCpuDllParameters(false);
|
||||
dllOption->appendProperty("SimDllName", cpuDllName);
|
||||
dllOption->appendProperty("SimDllArguments", simulatorCpuDllParameters);
|
||||
dllOption->appendProperty("TargetDllName", cpuDllName);
|
||||
dllOption->appendProperty("TargetDllArguments", targetCpuDllParameters);
|
||||
|
||||
QStringList includes;
|
||||
FilePaths headers;
|
||||
FilePaths sources;
|
||||
FilePaths assemblers;
|
||||
extractAllFiles(runTool, includes, headers, sources, assemblers);
|
||||
|
||||
if (toolsetNo == UvscServerProvider::ArmAdsToolsetNumber) {
|
||||
// Fill 'TargetArmAds' group (required for debugging).
|
||||
const auto targetArmAds = targetOption->appendPropertyGroup("TargetArmAds");
|
||||
// Fill 'ArmAdsMisc' group.
|
||||
const auto armAdsMisc = targetArmAds->appendPropertyGroup("ArmAdsMisc");
|
||||
// Fill 'OnChipMemories' group.
|
||||
const auto onChipMemories = armAdsMisc->appendPropertyGroup("OnChipMemories");
|
||||
|
||||
static const struct OnChipEntry {
|
||||
QString id;
|
||||
QByteArray name;
|
||||
int type = -1;
|
||||
} entries[] = {
|
||||
{"IROM1", "OCR_RVCT4", 1},
|
||||
{"IROM2", "OCR_RVCT5", 1},
|
||||
{"IRAM1", "OCR_RVCT9", 0},
|
||||
{"IRAM2", "OCR_RVCT10", 0},
|
||||
};
|
||||
|
||||
const auto entryBegin = std::cbegin(entries);
|
||||
const auto entryEnd = std::cend(entries);
|
||||
for (const DeviceSelection::Memory &memory : device.memories) {
|
||||
const auto entryIt = std::find_if(entryBegin, entryEnd,
|
||||
[memory](const OnChipEntry &entry) {
|
||||
return memory.id == entry.id;
|
||||
});
|
||||
if (entryIt == entryEnd)
|
||||
continue;
|
||||
|
||||
// Fill 'OCR_RVCTn' group.
|
||||
const auto ocrRvct = onChipMemories->appendPropertyGroup(entryIt->name);
|
||||
ocrRvct->appendProperty("Type", entryIt->type);
|
||||
ocrRvct->appendProperty("StartAddress", memory.start);
|
||||
ocrRvct->appendProperty("Size", memory.size);
|
||||
}
|
||||
|
||||
// Fill 'Cads' group.
|
||||
const auto cAds = targetArmAds->appendPropertyGroup("Cads");
|
||||
const auto variousControls = cAds->appendPropertyGroup("VariousControls");
|
||||
variousControls->appendMultiLineProperty("IncludePath", includes, ';');
|
||||
}
|
||||
|
||||
fillAllFiles(headers, sources, assemblers);
|
||||
}
|
||||
|
||||
void Project::fillAllFiles(const FilePaths &headers, const FilePaths &sources,
|
||||
const FilePaths &assemblers)
|
||||
{
|
||||
// Add headers, seources, and assembler files.
|
||||
const auto groups = m_target->appendPropertyGroup("Groups");
|
||||
const auto group = groups->appendPropertyGroup("Group");
|
||||
group->appendProperty("GroupName", "All Files");
|
||||
const auto filesGroup = group->appendPropertyGroup("Files");
|
||||
|
||||
enum FileType { SourceFile = 1, AssemblerFile = 2, HeaderFile = 5 };
|
||||
auto fillFile = [filesGroup](const FilePath &filePath, FileType fileType) {
|
||||
const auto fileGroup = filesGroup->appendPropertyGroup("File");
|
||||
fileGroup->appendProperty("FileName", filePath.fileName());
|
||||
fileGroup->appendProperty("FileType", fileType);
|
||||
fileGroup->appendProperty("FilePath", filePath.toString());
|
||||
};
|
||||
|
||||
// Add headers.
|
||||
for (const auto &header : headers)
|
||||
fillFile(header, FileType::HeaderFile);
|
||||
// Add sources.
|
||||
for (const auto &source : sources)
|
||||
fillFile(source, FileType::SourceFile);
|
||||
// Add assemblers.
|
||||
for (const auto &assembler : assemblers)
|
||||
fillFile(assembler, FileType::AssemblerFile);
|
||||
}
|
||||
|
||||
// ProjectOptions
|
||||
|
||||
ProjectOptions::ProjectOptions(const UvscServerProvider *provider)
|
||||
{
|
||||
appendProperty("SchemaVersion", kProjectSchema);
|
||||
appendProperty("Header", "### uVision Project, generated by QtCreator");
|
||||
|
||||
// Fill 'Target' group.
|
||||
const auto target = appendChild<Gen::Xml::PropertyGroup>("Target");
|
||||
target->appendProperty("TargetName", "Template");
|
||||
const int toolsetNo = provider->toolsetNumber();
|
||||
const QString toolsetNumber = buildToolsetNumber(toolsetNo);
|
||||
target->appendProperty("ToolsetNumber", toolsetNumber);
|
||||
|
||||
m_targetOption = target->appendPropertyGroup("TargetOption");
|
||||
|
||||
// Fill 'DebugOpt' group (required for dedugging).
|
||||
m_debugOpt = m_targetOption->appendPropertyGroup("DebugOpt");
|
||||
const bool useSimulator = provider->isSimulator();
|
||||
m_debugOpt->appendProperty("uSim", int(useSimulator));
|
||||
m_debugOpt->appendProperty("uTrg", int(!useSimulator));
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlproject.h"
|
||||
#include "xmlpropertygroup.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
namespace Debugger { class DebuggerRunTool; }
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
class UvscServerProvider;
|
||||
|
||||
namespace Uv {
|
||||
|
||||
// Helpers
|
||||
|
||||
QString toolsFilePath(const QString &uVisionFilePath);
|
||||
QString targetUVisionPath();
|
||||
|
||||
// UvProject
|
||||
|
||||
class Project final : public Gen::Xml::Project
|
||||
{
|
||||
public:
|
||||
explicit Project(const UvscServerProvider *provider, Debugger::DebuggerRunTool *runTool);
|
||||
|
||||
protected:
|
||||
Gen::Xml::PropertyGroup *m_target = nullptr;
|
||||
|
||||
private:
|
||||
void fillAllFiles(const Utils::FilePaths &headers, const Utils::FilePaths &sources,
|
||||
const Utils::FilePaths &assemblers);
|
||||
};
|
||||
|
||||
// ProjectOptions
|
||||
|
||||
class ProjectOptions : public Gen::Xml::ProjectOptions
|
||||
{
|
||||
public:
|
||||
explicit ProjectOptions(const UvscServerProvider *provider);
|
||||
|
||||
protected:
|
||||
Gen::Xml::PropertyGroup *m_targetOption = nullptr;
|
||||
Gen::Xml::PropertyGroup *m_debugOpt = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvprojectwriter.h"
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// ProjectWriter
|
||||
|
||||
ProjectWriter::ProjectWriter(std::ostream *device)
|
||||
: Gen::Xml::ProjectWriter(device)
|
||||
{
|
||||
}
|
||||
|
||||
void ProjectWriter::visitProjectStart(const Gen::Xml::Project *project)
|
||||
{
|
||||
Q_UNUSED(project)
|
||||
writer()->writeStartElement("Project");
|
||||
writer()->writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
writer()->writeAttribute("xsi:noNamespaceSchemaLocation", "project_proj.xsd");
|
||||
}
|
||||
|
||||
void ProjectWriter::visitProjectEnd(const Gen::Xml::Project *project)
|
||||
{
|
||||
Q_UNUSED(project)
|
||||
writer()->writeEndElement();
|
||||
}
|
||||
|
||||
// ProjectOptionsWriter
|
||||
|
||||
ProjectOptionsWriter::ProjectOptionsWriter(std::ostream *device)
|
||||
: Gen::Xml::ProjectOptionsWriter(device)
|
||||
{
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitProjectOptionsStart(
|
||||
const Gen::Xml::ProjectOptions *projectOptions)
|
||||
{
|
||||
Q_UNUSED(projectOptions)
|
||||
writer()->writeStartElement("ProjectOpt");
|
||||
writer()->writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
|
||||
writer()->writeAttribute("xsi:noNamespaceSchemaLocation", "project_optx.xsd");
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitProjectOptionsEnd(
|
||||
const Gen::Xml::ProjectOptions *projectOptions)
|
||||
{
|
||||
Q_UNUSED(projectOptions)
|
||||
writer()->writeEndElement();
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlprojectwriter.h"
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// ProjectWriter
|
||||
|
||||
class ProjectWriter final : public Gen::Xml::ProjectWriter
|
||||
{
|
||||
Q_DISABLE_COPY(ProjectWriter)
|
||||
public:
|
||||
explicit ProjectWriter(std::ostream *device);
|
||||
|
||||
private:
|
||||
void visitProjectStart(const Gen::Xml::Project *project) final;
|
||||
void visitProjectEnd(const Gen::Xml::Project *project) final;
|
||||
};
|
||||
|
||||
// ProjectOptionsWriter
|
||||
|
||||
class ProjectOptionsWriter final : public Gen::Xml::ProjectOptionsWriter
|
||||
{
|
||||
Q_DISABLE_COPY(ProjectOptionsWriter)
|
||||
public:
|
||||
explicit ProjectOptionsWriter(std::ostream *device);
|
||||
|
||||
private:
|
||||
void visitProjectOptionsStart(const Gen::Xml::ProjectOptions *projectOptions) final;
|
||||
void visitProjectOptionsEnd(const Gen::Xml::ProjectOptions *projectOptions) final;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,367 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h"
|
||||
#include "uvprojectwriter.h"
|
||||
#include "uvtargetdeviceviewer.h"
|
||||
#include "uvtargetdriverviewer.h"
|
||||
|
||||
#include "uvscserverprovider.h"
|
||||
|
||||
#include <baremetal/baremetaldebugsupport.h>
|
||||
#include <baremetal/baremetaldevice.h>
|
||||
#include <baremetal/debugserverprovidermanager.h>
|
||||
|
||||
#include <debugger/debuggerkitinformation.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/runconfigurationaspects.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QRegularExpressionValidator>
|
||||
|
||||
#include <fstream> // for std::ofstream
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
using namespace Uv;
|
||||
|
||||
// Whole software package selection keys.
|
||||
constexpr char deviceSelectionKeyC[] = "BareMetal.UvscServerProvider.DeviceSelection";
|
||||
constexpr char driverSelectionKeyC[] = "BareMetal.UvscServerProvider.DriverSelection";
|
||||
|
||||
constexpr int defaultPortNumber = 5101;
|
||||
|
||||
// UvscServerProvider
|
||||
|
||||
UvscServerProvider::UvscServerProvider(const QString &id)
|
||||
: IDebugServerProvider(id)
|
||||
{
|
||||
setEngineType(UvscEngineType);
|
||||
setChannel("localhost", defaultPortNumber);
|
||||
setToolsetNumber(ArmAdsToolsetNumber);
|
||||
}
|
||||
|
||||
UvscServerProvider::UvscServerProvider(const UvscServerProvider &other)
|
||||
: IDebugServerProvider(other.id())
|
||||
{
|
||||
setEngineType(UvscEngineType);
|
||||
}
|
||||
|
||||
void UvscServerProvider::setDeviceSelection(const DeviceSelection &deviceSelection)
|
||||
{
|
||||
m_deviceSelection = deviceSelection;
|
||||
}
|
||||
|
||||
DeviceSelection UvscServerProvider::deviceSelection() const
|
||||
{
|
||||
return m_deviceSelection;
|
||||
}
|
||||
|
||||
void UvscServerProvider::setDriverSelection(const DriverSelection &driverSelection)
|
||||
{
|
||||
m_driverSelection = driverSelection;
|
||||
}
|
||||
|
||||
DriverSelection UvscServerProvider::driverSelection() const
|
||||
{
|
||||
return m_driverSelection;
|
||||
}
|
||||
|
||||
void UvscServerProvider::setToolsetNumber(ToolsetNumber toolsetNumber)
|
||||
{
|
||||
m_toolsetNumber = toolsetNumber;
|
||||
}
|
||||
|
||||
UvscServerProvider::ToolsetNumber UvscServerProvider::toolsetNumber() const
|
||||
{
|
||||
return m_toolsetNumber;
|
||||
}
|
||||
|
||||
void UvscServerProvider::setSupportedDrivers(const QStringList &supportedDrivers)
|
||||
{
|
||||
m_supportedDrivers = supportedDrivers;
|
||||
}
|
||||
|
||||
QStringList UvscServerProvider::supportedDrivers() const
|
||||
{
|
||||
return m_supportedDrivers;
|
||||
}
|
||||
|
||||
bool UvscServerProvider::operator==(const IDebugServerProvider &other) const
|
||||
{
|
||||
if (!IDebugServerProvider::operator==(other))
|
||||
return false;
|
||||
const auto p = static_cast<const UvscServerProvider *>(&other);
|
||||
return m_deviceSelection == p->m_deviceSelection
|
||||
&& m_driverSelection == p->m_driverSelection
|
||||
&& m_toolsetNumber == p->m_toolsetNumber;
|
||||
}
|
||||
|
||||
FilePath UvscServerProvider::buildProjectFilePath(DebuggerRunTool *runTool) const
|
||||
{
|
||||
const RunControl *control = runTool->runControl();
|
||||
const QString projectName = control->project()->displayName() + ".uvprojx";
|
||||
const FilePath path = control->buildDirectory().pathAppended(projectName);
|
||||
return path;
|
||||
}
|
||||
|
||||
FilePath UvscServerProvider::buildOptionsFilePath(DebuggerRunTool *runTool) const
|
||||
{
|
||||
const RunControl *control = runTool->runControl();
|
||||
const QString projectName = control->project()->displayName() + ".uvoptx";
|
||||
const FilePath path = control->buildDirectory().pathAppended(projectName);
|
||||
return path;
|
||||
}
|
||||
|
||||
QVariantMap UvscServerProvider::toMap() const
|
||||
{
|
||||
QVariantMap data = IDebugServerProvider::toMap();
|
||||
data.insert(deviceSelectionKeyC, m_deviceSelection.toMap());
|
||||
data.insert(driverSelectionKeyC, m_driverSelection.toMap());
|
||||
return data;
|
||||
}
|
||||
|
||||
bool UvscServerProvider::isValid() const
|
||||
{
|
||||
return m_channel.isValid();
|
||||
}
|
||||
|
||||
QString UvscServerProvider::channelString() const
|
||||
{
|
||||
return m_channel.toString();
|
||||
}
|
||||
|
||||
bool UvscServerProvider::aboutToRun(DebuggerRunTool *runTool, QString &errorMessage) const
|
||||
{
|
||||
QTC_ASSERT(runTool, return false);
|
||||
const RunControl *runControl = runTool->runControl();
|
||||
const auto exeAspect = runControl->aspect<ExecutableAspect>();
|
||||
QTC_ASSERT(exeAspect, return false);
|
||||
|
||||
const FilePath bin = exeAspect->executable();
|
||||
if (bin.isEmpty()) {
|
||||
errorMessage = BareMetalDebugSupport::tr("Cannot debug: Local executable is not set.");
|
||||
return false;
|
||||
} else if (!bin.exists()) {
|
||||
errorMessage = BareMetalDebugSupport::tr(
|
||||
"Cannot debug: Could not find executable for \"%1\".").arg(bin.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
const FilePath projFilePath = projectFilePath(runTool, errorMessage);
|
||||
if (!projFilePath.exists())
|
||||
return false;
|
||||
|
||||
const FilePath optFilePath = optionsFilePath(runTool, errorMessage);
|
||||
if (!optFilePath.exists())
|
||||
return false;
|
||||
|
||||
Runnable inferior;
|
||||
inferior.executable = bin;
|
||||
inferior.extraData.insert(Debugger::Constants::kUVisionProjectFilePath, projFilePath.toString());
|
||||
inferior.extraData.insert(Debugger::Constants::kUVisionOptionsFilePath, optFilePath.toString());
|
||||
inferior.extraData.insert(Debugger::Constants::kUVisionSimulator, isSimulator());
|
||||
runTool->setInferior(inferior);
|
||||
runTool->setSymbolFile(bin);
|
||||
runTool->setStartMode(AttachToRemoteServer);
|
||||
runTool->setRemoteChannel(channelString());
|
||||
runTool->setUseContinueInsteadOfRun(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
ProjectExplorer::RunWorker *UvscServerProvider::targetRunner(RunControl *runControl) const
|
||||
{
|
||||
// Get uVision executable path.
|
||||
const Runnable uv = DebuggerKitAspect::runnable(runControl->kit());
|
||||
CommandLine server(uv.executable);
|
||||
server.addArg("-j0");
|
||||
server.addArg(QStringLiteral("-s%1").arg(m_channel.port()));
|
||||
|
||||
Runnable r;
|
||||
r.setCommandLine(server);
|
||||
return new UvscServerProviderRunner(runControl, r);
|
||||
}
|
||||
|
||||
bool UvscServerProvider::fromMap(const QVariantMap &data)
|
||||
{
|
||||
if (!IDebugServerProvider::fromMap(data))
|
||||
return false;
|
||||
m_deviceSelection.fromMap(data.value(deviceSelectionKeyC).toMap());
|
||||
m_driverSelection.fromMap(data.value(driverSelectionKeyC).toMap());
|
||||
return true;
|
||||
}
|
||||
|
||||
Utils::FilePath UvscServerProvider::projectFilePath(DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const
|
||||
{
|
||||
const FilePath projectPath = buildProjectFilePath(runTool);
|
||||
std::ofstream ofs(projectPath.toString().toStdString(), std::ofstream::out);
|
||||
Uv::ProjectWriter writer(&ofs);
|
||||
const Uv::Project project(this, runTool);
|
||||
if (!writer.write(&project)) {
|
||||
errorMessage = BareMetalDebugSupport::tr(
|
||||
"Unable to create an uVision project template");
|
||||
return {};
|
||||
}
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
// HexValueValidator
|
||||
|
||||
class HexValueValidator final : public QRegularExpressionValidator
|
||||
{
|
||||
public:
|
||||
explicit HexValueValidator(QObject *parent = nullptr)
|
||||
: QRegularExpressionValidator(parent)
|
||||
{
|
||||
const QRegularExpression re("^0x[0-9a-fA-F]{1,8}");
|
||||
setRegularExpression(re);
|
||||
}
|
||||
};
|
||||
|
||||
// UvscServerProviderConfigWidget
|
||||
|
||||
UvscServerProviderConfigWidget::UvscServerProviderConfigWidget(UvscServerProvider *provider)
|
||||
: IDebugServerProviderConfigWidget(provider)
|
||||
{
|
||||
m_hostWidget = new HostWidget;
|
||||
m_mainLayout->addRow(tr("Host:"), m_hostWidget);
|
||||
m_deviceSelector = new DeviceSelector;
|
||||
m_mainLayout->addRow(tr("Target device:"), m_deviceSelector);
|
||||
m_driverSelector = new DriverSelector(provider->supportedDrivers());
|
||||
m_mainLayout->addRow(tr("Target driver:"), m_driverSelector);
|
||||
|
||||
setFromProvider();
|
||||
|
||||
connect(m_hostWidget, &HostWidget::dataChanged,
|
||||
this, &UvscServerProviderConfigWidget::dirty);
|
||||
connect(m_deviceSelector, &DeviceSelector::selectionChanged,
|
||||
this, &UvscServerProviderConfigWidget::dirty);
|
||||
connect(m_driverSelector, &DriverSelector::selectionChanged,
|
||||
this, &UvscServerProviderConfigWidget::dirty);
|
||||
}
|
||||
|
||||
void UvscServerProviderConfigWidget::apply()
|
||||
{
|
||||
const auto p = static_cast<UvscServerProvider *>(m_provider);
|
||||
p->setDeviceSelection(deviceSelection());
|
||||
p->setDriverSelection(driverSelection());
|
||||
IDebugServerProviderConfigWidget::apply();
|
||||
}
|
||||
|
||||
void UvscServerProviderConfigWidget::discard()
|
||||
{
|
||||
setFromProvider();
|
||||
IDebugServerProviderConfigWidget::discard();
|
||||
}
|
||||
|
||||
void UvscServerProviderConfigWidget::setDeviceSelection(const DeviceSelection &deviceSelection)
|
||||
{
|
||||
m_deviceSelector->setSelection(deviceSelection);
|
||||
}
|
||||
|
||||
DeviceSelection UvscServerProviderConfigWidget::deviceSelection() const
|
||||
{
|
||||
return m_deviceSelector->selection();
|
||||
}
|
||||
|
||||
void UvscServerProviderConfigWidget::setDriverSelection(const DriverSelection &driverSelection)
|
||||
{
|
||||
m_driverSelector->setSelection(driverSelection);
|
||||
}
|
||||
|
||||
DriverSelection UvscServerProviderConfigWidget::driverSelection() const
|
||||
{
|
||||
return m_driverSelector->selection();
|
||||
}
|
||||
|
||||
void UvscServerProviderConfigWidget::setFromProvider()
|
||||
{
|
||||
const auto p = static_cast<UvscServerProvider *>(m_provider);
|
||||
m_hostWidget->setChannel(p->channel());
|
||||
m_deviceSelector->setSelection(p->deviceSelection());
|
||||
m_driverSelector->setSelection(p->driverSelection());
|
||||
}
|
||||
|
||||
// UvscServerProviderRunner
|
||||
|
||||
UvscServerProviderRunner::UvscServerProviderRunner(ProjectExplorer::RunControl *runControl,
|
||||
const Runnable &runnable)
|
||||
: RunWorker(runControl)
|
||||
{
|
||||
setId("BareMetalUvscServer");
|
||||
|
||||
const QString program = runnable.executable.toString();
|
||||
const QStringList args = runnable.commandLineArguments.split(' ');
|
||||
m_process.setProgram(program);
|
||||
m_process.setArguments(args);
|
||||
|
||||
connect(&m_process, &QtcProcess::started, this, [this]() {
|
||||
ProcessHandle pid(m_process.processId());
|
||||
this->runControl()->setApplicationProcessHandle(pid);
|
||||
reportStarted();
|
||||
});
|
||||
connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QtcProcess::finished),
|
||||
this, [this] (int exitCode, QProcess::ExitStatus status) {
|
||||
const QString msg = (status == QProcess::CrashExit)
|
||||
? tr("%1 crashed.") : tr("%2 exited with code %1").arg(exitCode);
|
||||
appendMessage(msg.arg(m_process.program()), Utils::NormalMessageFormat);
|
||||
reportStopped();
|
||||
});
|
||||
connect(&m_process, &QtcProcess::errorOccurred, this, [this] (QProcess::ProcessError error) {
|
||||
if (error == QProcess::Timedout)
|
||||
return; // No actual change on the process side.
|
||||
const QString msg = userMessageForProcessError(
|
||||
error, FilePath::fromString(m_process.program()));
|
||||
appendMessage(msg, Utils::NormalMessageFormat);
|
||||
reportStopped();
|
||||
});
|
||||
}
|
||||
|
||||
void UvscServerProviderRunner::start()
|
||||
{
|
||||
const QString msg = RunControl::tr("Starting %1 %2...")
|
||||
.arg(m_process.program()).arg(m_process.arguments().join(' '));
|
||||
appendMessage(msg, Utils::NormalMessageFormat);
|
||||
|
||||
m_process.start();
|
||||
}
|
||||
|
||||
void UvscServerProviderRunner::stop()
|
||||
{
|
||||
m_process.terminate();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,144 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvtargetdeviceselection.h"
|
||||
#include "uvtargetdriverselection.h"
|
||||
|
||||
#include <baremetal/idebugserverprovider.h>
|
||||
|
||||
#include <projectexplorer/runcontrol.h> // for RunWorker
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
namespace Uv {
|
||||
class DeviceSelection;
|
||||
class DeviceSelector;
|
||||
class DriverSelection;
|
||||
class DriverSelector;
|
||||
}
|
||||
|
||||
// UvscServerProvider
|
||||
|
||||
class UvscServerProvider : public IDebugServerProvider
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(BareMetal::Internal::UvscServerProvider)
|
||||
|
||||
public:
|
||||
enum ToolsetNumber {
|
||||
UnknownToolsetNumber = -1,
|
||||
ArmAdsToolsetNumber = 4 // ARM-ADS toolset
|
||||
};
|
||||
|
||||
void setDeviceSelection(const Uv::DeviceSelection &deviceSelection);
|
||||
Uv::DeviceSelection deviceSelection() const;
|
||||
|
||||
void setDriverSelection(const Uv::DriverSelection &driverSelection);
|
||||
Uv::DriverSelection driverSelection() const;
|
||||
|
||||
ToolsetNumber toolsetNumber() const;
|
||||
QStringList supportedDrivers() const;
|
||||
|
||||
bool operator==(const IDebugServerProvider &other) const override;
|
||||
|
||||
QVariantMap toMap() const override;
|
||||
|
||||
bool aboutToRun(Debugger::DebuggerRunTool *runTool, QString &errorMessage) const final;
|
||||
ProjectExplorer::RunWorker *targetRunner(ProjectExplorer::RunControl *runControl) const final;
|
||||
|
||||
bool isValid() const override;
|
||||
QString channelString() const final;
|
||||
|
||||
protected:
|
||||
explicit UvscServerProvider(const QString &id);
|
||||
explicit UvscServerProvider(const UvscServerProvider &other);
|
||||
|
||||
void setToolsetNumber(ToolsetNumber toolsetNumber);
|
||||
void setSupportedDrivers(const QStringList &supportedDrivers);
|
||||
|
||||
Utils::FilePath buildProjectFilePath(Debugger::DebuggerRunTool *runTool) const;
|
||||
Utils::FilePath buildOptionsFilePath(Debugger::DebuggerRunTool *runTool) const;
|
||||
|
||||
bool fromMap(const QVariantMap &data) override;
|
||||
|
||||
// uVision specific stuff.
|
||||
virtual Utils::FilePath projectFilePath(Debugger::DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const;
|
||||
virtual Utils::FilePath optionsFilePath(Debugger::DebuggerRunTool *runTool,
|
||||
QString &errorMessage) const = 0;
|
||||
|
||||
Uv::DeviceSelection m_deviceSelection;
|
||||
Uv::DriverSelection m_driverSelection;
|
||||
|
||||
// Note: Don't store it to the map!
|
||||
ToolsetNumber m_toolsetNumber = UnknownToolsetNumber;
|
||||
QStringList m_supportedDrivers;
|
||||
|
||||
friend class UvscServerProviderConfigWidget;
|
||||
};
|
||||
|
||||
// UvscServerProviderConfigWidget
|
||||
|
||||
class UvscServerProviderConfigWidget : public IDebugServerProviderConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UvscServerProviderConfigWidget(UvscServerProvider *provider);
|
||||
void apply() override;
|
||||
void discard() override;
|
||||
|
||||
protected:
|
||||
void setDeviceSelection(const Uv::DeviceSelection &deviceSelection);
|
||||
Uv::DeviceSelection deviceSelection() const;
|
||||
void setDriverSelection(const Uv::DriverSelection &driverSelection);
|
||||
Uv::DriverSelection driverSelection() const;
|
||||
|
||||
void setFromProvider();
|
||||
|
||||
HostWidget *m_hostWidget = nullptr;
|
||||
Uv::DeviceSelector *m_deviceSelector = nullptr;
|
||||
Uv::DriverSelector *m_driverSelector = nullptr;
|
||||
};
|
||||
|
||||
// UvscServerProviderRunner
|
||||
|
||||
class UvscServerProviderRunner final : public ProjectExplorer::RunWorker
|
||||
{
|
||||
public:
|
||||
explicit UvscServerProviderRunner(ProjectExplorer::RunControl *runControl,
|
||||
const ProjectExplorer::Runnable &runnable);
|
||||
|
||||
private:
|
||||
void start() final;
|
||||
void stop() final;
|
||||
|
||||
QProcess m_process;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,34 @@
|
||||
HEADERS += \
|
||||
$$PWD/simulatoruvscserverprovider.h \
|
||||
$$PWD/stlinkuvscserverprovider.h \
|
||||
$$PWD/uvproject.h \
|
||||
$$PWD/uvprojectwriter.h \
|
||||
$$PWD/uvscserverprovider.h \
|
||||
$$PWD/uvtargetdevicemodel.h \
|
||||
$$PWD/uvtargetdeviceselection.h \
|
||||
$$PWD/uvtargetdeviceviewer.h \
|
||||
$$PWD/uvtargetdrivermodel.h \
|
||||
$$PWD/uvtargetdriverselection.h \
|
||||
$$PWD/uvtargetdriverviewer.h \
|
||||
$$PWD/xmlnodevisitor.h \
|
||||
$$PWD/xmlproject.h \
|
||||
$$PWD/xmlprojectwriter.h \
|
||||
$$PWD/xmlproperty.h \
|
||||
$$PWD/xmlpropertygroup.h \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/simulatoruvscserverprovider.cpp \
|
||||
$$PWD/stlinkuvscserverprovider.cpp \
|
||||
$$PWD/uvproject.cpp \
|
||||
$$PWD/uvprojectwriter.cpp \
|
||||
$$PWD/uvscserverprovider.cpp \
|
||||
$$PWD/uvtargetdevicemodel.cpp \
|
||||
$$PWD/uvtargetdeviceselection.cpp \
|
||||
$$PWD/uvtargetdeviceviewer.cpp \
|
||||
$$PWD/uvtargetdrivermodel.cpp \
|
||||
$$PWD/uvtargetdriverselection.cpp \
|
||||
$$PWD/uvtargetdriverviewer.cpp \
|
||||
$$PWD/xmlproject.cpp \
|
||||
$$PWD/xmlprojectwriter.cpp \
|
||||
$$PWD/xmlproperty.cpp \
|
||||
$$PWD/xmlpropertygroup.cpp \
|
||||
@@ -0,0 +1,506 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h" // for toolsFilePath()
|
||||
#include "uvtargetdevicemodel.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
static QString extractPacksPath(const QString &uVisionFilePath)
|
||||
{
|
||||
QFile f(toolsFilePath(uVisionFilePath));
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
return {};
|
||||
QTextStream in(&f);
|
||||
while (!in.atEnd()) {
|
||||
const QByteArray line = f.readLine().trimmed();
|
||||
const auto startIndex = line.indexOf("RTEPATH=\"");
|
||||
const auto stopIndex = line.lastIndexOf('"');
|
||||
if (startIndex != 0 || (stopIndex + 1) != line.size())
|
||||
continue;
|
||||
const QFileInfo path(QString::fromUtf8(line.mid(startIndex + 9,
|
||||
stopIndex - startIndex - 9)));
|
||||
if (!path.exists())
|
||||
return {};
|
||||
return path.absoluteFilePath();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static QString extractPackVersion(const QString &packFilePath)
|
||||
{
|
||||
return QFileInfo(packFilePath).dir().dirName();
|
||||
}
|
||||
|
||||
static QStringList findKeilPackFiles(const QString &path)
|
||||
{
|
||||
QStringList files;
|
||||
// Search for the STMicroelectronics devices.
|
||||
QDirIterator it(path, {"STM*_DFP"}, QDir::Dirs);
|
||||
while (it.hasNext()) {
|
||||
const QDir dfpDir(it.next());
|
||||
const QFileInfoList entries = dfpDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
|
||||
QDir::Name);
|
||||
if (entries.isEmpty())
|
||||
continue;
|
||||
QDirIterator fit(entries.last().absoluteFilePath(), {"*.pdsc"},
|
||||
QDir::Files | QDir::NoSymLinks);
|
||||
while (fit.hasNext())
|
||||
files.push_back(fit.next());
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
static void fillCpu(QXmlStreamReader &in, DeviceSelection::Cpu &cpu)
|
||||
{
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
in.skipCurrentElement();
|
||||
cpu.core = attrs.hasAttribute("Dcore") ? attrs.value("Dcore").toString() : cpu.core;
|
||||
cpu.clock = attrs.hasAttribute("Dclock") ? attrs.value("Dclock").toString() : cpu.clock;
|
||||
cpu.fpu = attrs.hasAttribute("Dfpu") ? attrs.value("Dfpu").toString() : cpu.fpu;
|
||||
cpu.mpu = attrs.hasAttribute("Dmpu") ? attrs.value("Dmpu").toString() : cpu.mpu;
|
||||
}
|
||||
|
||||
static void fillMemories(QXmlStreamReader &in, DeviceSelection::Memories &memories)
|
||||
{
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
in.skipCurrentElement();
|
||||
DeviceSelection::Memory memory;
|
||||
memory.id = attrs.value("id").toString();
|
||||
memory.start = attrs.value("start").toString();
|
||||
memory.size = attrs.value("size").toString();
|
||||
memories.push_back(memory);
|
||||
}
|
||||
|
||||
static void fillAlgorithms(QXmlStreamReader &in, DeviceSelection::Algorithms &algorithms)
|
||||
{
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
in.skipCurrentElement();
|
||||
DeviceSelection::Algorithm algorithm;
|
||||
algorithm.path = attrs.value("name").toString();
|
||||
algorithm.start = attrs.value("start").toString();
|
||||
algorithm.size = attrs.value("size").toString();
|
||||
algorithms.push_back(algorithm);
|
||||
}
|
||||
|
||||
// DeviceSelectionItem
|
||||
|
||||
class DeviceSelectionItem : public TreeItem
|
||||
{
|
||||
public:
|
||||
enum class Type { Unknown, Package, Family, SubFamily, Device, DeviceVariant };
|
||||
enum Column { NameColumn, VersionColumn, VendorColumn };
|
||||
explicit DeviceSelectionItem(Type type = Type::Unknown)
|
||||
: m_type(type)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const override
|
||||
{
|
||||
if (role == Qt::DisplayRole && column == NameColumn)
|
||||
return m_name;
|
||||
return {};
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags(int column) const override
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
return Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
DeviceSelectionItem *parentPackItem() const
|
||||
{
|
||||
return static_cast<DeviceSelectionItem *>(parent());
|
||||
}
|
||||
|
||||
QString m_name;
|
||||
const Type m_type;
|
||||
};
|
||||
|
||||
// PackageItem
|
||||
|
||||
class PackageItem final : public DeviceSelectionItem
|
||||
{
|
||||
public:
|
||||
explicit PackageItem(const QString &file)
|
||||
: DeviceSelectionItem(Type::Package), m_file(file), m_version(extractPackVersion(file))
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (column == NameColumn)
|
||||
return m_name;
|
||||
else if (column == VersionColumn)
|
||||
return m_version;
|
||||
else if (column == VendorColumn)
|
||||
return m_vendor;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString m_version;
|
||||
QString m_file;
|
||||
QString m_desc;
|
||||
QString m_vendor;
|
||||
QString m_url;
|
||||
};
|
||||
|
||||
// FamilyItem
|
||||
|
||||
class FamilyItem final : public DeviceSelectionItem
|
||||
{
|
||||
public:
|
||||
explicit FamilyItem()
|
||||
: DeviceSelectionItem(Type::Family)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (column == NameColumn) {
|
||||
return m_name;
|
||||
} else if (column == VendorColumn) {
|
||||
const auto colonIndex = m_vendor.lastIndexOf(':');
|
||||
return m_vendor.mid(0, colonIndex);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString m_desc;
|
||||
QString m_vendor;
|
||||
};
|
||||
|
||||
// SubFamilyItem
|
||||
|
||||
class SubFamilyItem final : public DeviceSelectionItem
|
||||
{
|
||||
public:
|
||||
explicit SubFamilyItem()
|
||||
: DeviceSelectionItem(Type::SubFamily)
|
||||
{}
|
||||
|
||||
QString m_svd;
|
||||
};
|
||||
|
||||
// DeviceItem
|
||||
|
||||
class DeviceItem final : public DeviceSelectionItem
|
||||
{
|
||||
public:
|
||||
explicit DeviceItem()
|
||||
: DeviceSelectionItem(Type::Device)
|
||||
{}
|
||||
|
||||
Qt::ItemFlags flags(int column) const final
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
return hasChildren() ? Qt::ItemIsEnabled : (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
DeviceSelection::Cpu m_cpu;
|
||||
DeviceSelection::Memories m_memories;
|
||||
DeviceSelection::Algorithms m_algorithms;
|
||||
};
|
||||
|
||||
// DeviceVariantItem
|
||||
|
||||
class DeviceVariantItem final : public DeviceSelectionItem
|
||||
{
|
||||
public:
|
||||
explicit DeviceVariantItem()
|
||||
: DeviceSelectionItem(Type::DeviceVariant)
|
||||
{}
|
||||
|
||||
Qt::ItemFlags flags(int column) const final
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
};
|
||||
|
||||
// DeviceSelectionModel
|
||||
|
||||
DeviceSelectionModel::DeviceSelectionModel(QObject *parent)
|
||||
: TreeModel<DeviceSelectionItem>(parent)
|
||||
{
|
||||
setHeader({tr("Name"), tr("Version"), tr("Vendor")});
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::fillAllPacks(const QString &uVisionFilePath)
|
||||
{
|
||||
if (m_uVisionFilePath == uVisionFilePath)
|
||||
return;
|
||||
|
||||
clear();
|
||||
|
||||
m_uVisionFilePath = uVisionFilePath;
|
||||
const QString packsPath = extractPacksPath(m_uVisionFilePath);
|
||||
if (packsPath.isEmpty())
|
||||
return;
|
||||
|
||||
QStringList allPackFiles;
|
||||
QDirIterator it(packsPath, {"Keil"}, QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
while (it.hasNext()) {
|
||||
const QString path = it.next();
|
||||
if (path.endsWith("/Keil"))
|
||||
allPackFiles << findKeilPackFiles(path);
|
||||
}
|
||||
|
||||
if (allPackFiles.isEmpty())
|
||||
return;
|
||||
for (const QString &packFile : qAsConst(allPackFiles))
|
||||
parsePackage(packFile);
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parsePackage(const QString &packageFile)
|
||||
{
|
||||
QFile f(packageFile);
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
return;
|
||||
QXmlStreamReader in(&f);
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "package")
|
||||
parsePackage(in, packageFile);
|
||||
else
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parsePackage(QXmlStreamReader &in, const QString &file)
|
||||
{
|
||||
const auto child = new PackageItem(file);
|
||||
rootItem()->appendChild(child);
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "name") {
|
||||
child->m_name = in.readElementText().trimmed();
|
||||
} else if (elementName == "description") {
|
||||
child->m_desc = in.readElementText().trimmed();
|
||||
} else if (elementName == "vendor") {
|
||||
child->m_vendor = in.readElementText().trimmed();
|
||||
} else if (elementName == "url") {
|
||||
child->m_url = in.readElementText().trimmed();
|
||||
} else if (elementName == "devices") {
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "family")
|
||||
parseFamily(in, child);
|
||||
else
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
} else {
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parseFamily(QXmlStreamReader &in, DeviceSelectionItem *parent)
|
||||
{
|
||||
const auto child = new FamilyItem;
|
||||
parent->appendChild(child);
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
child->m_name = attrs.value("Dfamily").toString();
|
||||
child->m_vendor = attrs.value("Dvendor").toString();
|
||||
DeviceSelection::Cpu cpu;
|
||||
DeviceSelection::Memories memories;
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "processor") {
|
||||
fillCpu(in, cpu);
|
||||
} else if (elementName == "memory") {
|
||||
fillMemories(in, memories);
|
||||
} else if (elementName == "description") {
|
||||
child->m_desc = in.readElementText().trimmed();
|
||||
} else if (elementName == "subFamily") {
|
||||
parseSubFamily(in, child, cpu);
|
||||
} else if (elementName == "device") {
|
||||
parseDevice(in, child, cpu, memories);
|
||||
} else {
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent,
|
||||
DeviceSelection::Cpu &cpu)
|
||||
{
|
||||
const auto child = new SubFamilyItem;
|
||||
parent->appendChild(child);
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
child->m_name = attrs.value("DsubFamily").toString();
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "processor") {
|
||||
fillCpu(in, cpu);
|
||||
} else if (elementName == "debug") {
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
in.skipCurrentElement();
|
||||
child->m_svd = attrs.value("svd").toString();
|
||||
} else if (elementName == "device") {
|
||||
DeviceSelection::Memories memories;
|
||||
parseDevice(in, child, cpu, memories);
|
||||
} else {
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent,
|
||||
DeviceSelection::Cpu &cpu,
|
||||
DeviceSelection::Memories &memories)
|
||||
{
|
||||
const auto child = new DeviceItem;
|
||||
parent->appendChild(child);
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
child->m_name = attrs.value("Dname").toString();
|
||||
DeviceSelection::Algorithms algorithms;
|
||||
while (in.readNextStartElement()) {
|
||||
const QStringRef elementName = in.name();
|
||||
if (elementName == "processor") {
|
||||
fillCpu(in, cpu);
|
||||
} else if (elementName == "memory") {
|
||||
fillMemories(in, memories);
|
||||
} else if (elementName == "algorithm") {
|
||||
fillAlgorithms(in, algorithms);
|
||||
} else if (elementName == "variant") {
|
||||
parseDeviceVariant(in, child);
|
||||
} else {
|
||||
in.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
child->m_cpu = cpu;
|
||||
child->m_memories = memories;
|
||||
child->m_algorithms = algorithms;
|
||||
}
|
||||
|
||||
void DeviceSelectionModel::parseDeviceVariant(QXmlStreamReader &in, DeviceSelectionItem *parent)
|
||||
{
|
||||
const auto child = new DeviceVariantItem;
|
||||
parent->appendChild(child);
|
||||
const QXmlStreamAttributes attrs = in.attributes();
|
||||
in.skipCurrentElement();
|
||||
child->m_name = attrs.value("Dvariant").toString();
|
||||
}
|
||||
|
||||
// DeviceSelectionView
|
||||
|
||||
DeviceSelectionView::DeviceSelectionView(QWidget *parent)
|
||||
: TreeView(parent)
|
||||
{
|
||||
setRootIsDecorated(true);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
}
|
||||
|
||||
void DeviceSelectionView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
Q_UNUSED(previous)
|
||||
|
||||
if (!current.isValid())
|
||||
return;
|
||||
const auto selectionModel = qobject_cast<DeviceSelectionModel *>(model());
|
||||
if (!selectionModel)
|
||||
return;
|
||||
const DeviceSelectionItem *item = selectionModel->itemForIndex(current);
|
||||
if (isValidItem(item)) {
|
||||
const auto selection = buildSelection(item);
|
||||
if (!selection.name.isEmpty())
|
||||
emit deviceSelected(selection);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceSelectionView::isValidItem(const DeviceSelectionItem *item) const
|
||||
{
|
||||
if (!item)
|
||||
return false;
|
||||
if (item->m_type == DeviceSelectionItem::Type::DeviceVariant)
|
||||
return true;
|
||||
if (item->m_type == DeviceSelectionItem::Type::Device && !item->hasChildren())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceSelection DeviceSelectionView::buildSelection(const DeviceSelectionItem *item) const
|
||||
{
|
||||
DeviceSelection selection;
|
||||
// We need to iterate from the lower 'Device|DeviceVariant' items to
|
||||
// the upper 'Package' item to fill whole information.
|
||||
do {
|
||||
switch (item->m_type) {
|
||||
case DeviceSelectionItem::Type::DeviceVariant:
|
||||
selection.name = item->m_name;
|
||||
break;
|
||||
case DeviceSelectionItem::Type::Device: {
|
||||
const auto deviceItem = static_cast<const DeviceItem *>(item);
|
||||
if (!deviceItem->hasChildren())
|
||||
selection.name = item->m_name;
|
||||
selection.cpu = deviceItem->m_cpu;
|
||||
selection.memories = deviceItem->m_memories;
|
||||
selection.algorithms = deviceItem->m_algorithms;
|
||||
}
|
||||
break;
|
||||
case DeviceSelectionItem::Type::SubFamily: {
|
||||
const auto subFamilyItem = static_cast<const SubFamilyItem *>(item);
|
||||
selection.subfamily = subFamilyItem->m_name;
|
||||
selection.svd = subFamilyItem->m_svd;
|
||||
}
|
||||
break;
|
||||
case DeviceSelectionItem::Type::Family: {
|
||||
const auto familyItem = static_cast<const FamilyItem *>(item);
|
||||
selection.family = familyItem->m_name;
|
||||
selection.desc = familyItem->m_desc;
|
||||
selection.vendor = familyItem->m_vendor;
|
||||
}
|
||||
break;
|
||||
case DeviceSelectionItem::Type::Package: {
|
||||
const auto packageItem = static_cast<const PackageItem *>(item);
|
||||
selection.package.desc = packageItem->m_desc;
|
||||
selection.package.file = packageItem->m_file;
|
||||
selection.package.name = packageItem->m_name;
|
||||
selection.package.url = packageItem->m_url;
|
||||
selection.package.vendor = packageItem->m_vendor;
|
||||
selection.package.version = packageItem->m_version;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (item = item->parentPackItem());
|
||||
return selection;
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvtargetdeviceselection.h"
|
||||
|
||||
#include <utils/basetreeview.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QXmlStreamReader;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DeviceSelectionModel
|
||||
|
||||
class DeviceSelectionItem;
|
||||
class DeviceSelectionModel final : public Utils::TreeModel<DeviceSelectionItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionModel(QObject *parent = nullptr);
|
||||
void fillAllPacks(const QString &uVisionFilePath);
|
||||
|
||||
private:
|
||||
void parsePackage(const QString &packageFile);
|
||||
void parsePackage(QXmlStreamReader &in, const QString &file);
|
||||
void parseFamily(QXmlStreamReader &in, DeviceSelectionItem *parent);
|
||||
void parseSubFamily(QXmlStreamReader &in, DeviceSelectionItem *parent,
|
||||
DeviceSelection::Cpu &cpu);
|
||||
void parseDevice(QXmlStreamReader &in, DeviceSelectionItem *parent,
|
||||
DeviceSelection::Cpu &cpu, DeviceSelection::Memories &memories);
|
||||
void parseDeviceVariant(QXmlStreamReader &in, DeviceSelectionItem *parent);
|
||||
|
||||
QString m_uVisionFilePath;
|
||||
};
|
||||
|
||||
// DeviceSelectionView
|
||||
|
||||
class DeviceSelectionView final : public Utils::TreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeviceSelectionView(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void deviceSelected(const DeviceSelection &selection);
|
||||
|
||||
private:
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) final;
|
||||
|
||||
bool isValidItem(const DeviceSelectionItem *item) const;
|
||||
DeviceSelection buildSelection(const DeviceSelectionItem *item) const;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,415 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvtargetdeviceselection.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDataWidgetMapper>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// Software package data keys.
|
||||
constexpr char packageDescrKeyC[] = "BareMetal.UvscServerProvider.PackageDescription";
|
||||
constexpr char packageFileKeyC[] = "BareMetal.UvscServerProvider.PackageFile";
|
||||
constexpr char packageNameKeyC[] = "BareMetal.UvscServerProvider.PackageName";
|
||||
constexpr char packageUrlKeyC[] = "BareMetal.UvscServerProvider.PackageUrl";
|
||||
constexpr char packageVendorKeyC[] = "BareMetal.UvscServerProvider.PackageVendor";
|
||||
constexpr char packageVersionKeyC[] = "BareMetal.UvscServerProvider.PackageVersion";
|
||||
// Device data keys.
|
||||
constexpr char deviceNameKeyC[] = "BareMetal.UvscServerProvider.DeviceName";
|
||||
constexpr char deviceDescrKeyC[] = "BareMetal.UvscServerProvider.DeviceDescription";
|
||||
constexpr char deviceFamilyKeyC[] = "BareMetal.UvscServerProvider.DeviceFamily";
|
||||
constexpr char deviceSubFamilyKeyC[] = "BareMetal.UvscServerProvider.DeviceSubFamily";
|
||||
constexpr char deviceVendorKeyC[] = "BareMetal.UvscServerProvider.DeviceVendor";
|
||||
constexpr char deviceSvdKeyC[] = "BareMetal.UvscServerProvider.DeviceSVD";
|
||||
// Device CPU data keys.
|
||||
constexpr char deviceClockKeyC[] = "BareMetal.UvscServerProvider.DeviceClock";
|
||||
constexpr char deviceCoreKeyC[] = "BareMetal.UvscServerProvider.DeviceCore";
|
||||
constexpr char deviceFpuKeyC[] = "BareMetal.UvscServerProvider.DeviceFPU";
|
||||
constexpr char deviceMpuKeyC[] = "BareMetal.UvscServerProvider.DeviceMPU";
|
||||
// Device MEMORY data keys.
|
||||
constexpr char deviceMemoryKeyC[] = "BareMetal.UvscServerProvider.DeviceMemory";
|
||||
constexpr char deviceMemoryIdKeyC[] = "BareMetal.UvscServerProvider.DeviceMemoryId";
|
||||
constexpr char deviceMemoryStartKeyC[] = "BareMetal.UvscServerProvider.DeviceMemoryStart";
|
||||
constexpr char deviceMemorySizeKeyC[] = "BareMetal.UvscServerProvider.DeviceMemorySize";
|
||||
// Device ALGORITHM data keys.
|
||||
constexpr char deviceAlgorithmKeyC[] = "BareMetal.UvscServerProvider.DeviceAlgorithm";
|
||||
constexpr char deviceAlgorithmPathKeyC[] = "BareMetal.UvscServerProvider.DeviceAlgorithmPath";
|
||||
constexpr char deviceAlgorithmStartKeyC[] = "BareMetal.UvscServerProvider.DeviceAlgorithmStart";
|
||||
constexpr char deviceAlgorithmSizeKeyC[] = "BareMetal.UvscServerProvider.DeviceAlgorithmSize";
|
||||
constexpr char deviceAlgorithmIndexKeyC[] = "BareMetal.UvscServerProvider.DeviceAlgorithmIndex";
|
||||
|
||||
// DeviceSelection
|
||||
|
||||
QVariantMap DeviceSelection::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
// Software package.
|
||||
map.insert(packageDescrKeyC, package.desc);
|
||||
map.insert(packageFileKeyC, package.file);
|
||||
map.insert(packageNameKeyC, package.name);
|
||||
map.insert(packageUrlKeyC, package.url);
|
||||
map.insert(packageVendorKeyC, package.vendor);
|
||||
map.insert(packageVersionKeyC, package.version);
|
||||
// Device.
|
||||
map.insert(deviceNameKeyC, name);
|
||||
map.insert(deviceDescrKeyC, desc);
|
||||
map.insert(deviceFamilyKeyC, family);
|
||||
map.insert(deviceSubFamilyKeyC, subfamily);
|
||||
map.insert(deviceVendorKeyC, vendor);
|
||||
map.insert(deviceSvdKeyC, svd);
|
||||
// Device CPU.
|
||||
map.insert(deviceClockKeyC, cpu.clock);
|
||||
map.insert(deviceCoreKeyC, cpu.core);
|
||||
map.insert(deviceFpuKeyC, cpu.fpu);
|
||||
map.insert(deviceMpuKeyC, cpu.mpu);
|
||||
// Device MEMORY.
|
||||
QVariantList memoryList;
|
||||
for (const DeviceSelection::Memory &memory : qAsConst(memories)) {
|
||||
QVariantMap m;
|
||||
m.insert(deviceMemoryIdKeyC, memory.id);
|
||||
m.insert(deviceMemoryStartKeyC, memory.start);
|
||||
m.insert(deviceMemorySizeKeyC, memory.size);
|
||||
memoryList.push_back(m);
|
||||
}
|
||||
map.insert(deviceMemoryKeyC, memoryList);
|
||||
// Device ALGORITHM.
|
||||
QVariantList algorithmList;
|
||||
for (const DeviceSelection::Algorithm &algorithm : qAsConst(algorithms)) {
|
||||
QVariantMap m;
|
||||
m.insert(deviceAlgorithmPathKeyC, algorithm.path);
|
||||
m.insert(deviceAlgorithmStartKeyC, algorithm.start);
|
||||
m.insert(deviceAlgorithmSizeKeyC, algorithm.size);
|
||||
algorithmList.push_back(m);
|
||||
}
|
||||
map.insert(deviceAlgorithmKeyC, algorithmList);
|
||||
map.insert(deviceAlgorithmIndexKeyC, algorithmIndex);
|
||||
return map;
|
||||
}
|
||||
|
||||
void DeviceSelection::fromMap(const QVariantMap &map)
|
||||
{
|
||||
// Software package.
|
||||
package.desc = map.value(packageDescrKeyC).toString();
|
||||
package.file = map.value(packageFileKeyC).toString();
|
||||
package.name = map.value(packageNameKeyC).toString();
|
||||
package.url = map.value(packageUrlKeyC).toString();
|
||||
package.vendor = map.value(packageVendorKeyC).toString();
|
||||
package.version = map.value(packageVersionKeyC).toString();
|
||||
// Device.
|
||||
name = map.value(deviceNameKeyC).toString();
|
||||
desc = map.value(deviceDescrKeyC).toString();
|
||||
family = map.value(deviceFamilyKeyC).toString();
|
||||
subfamily = map.value(deviceSubFamilyKeyC).toString();
|
||||
vendor = map.value(deviceVendorKeyC).toString();
|
||||
svd = map.value(deviceSvdKeyC).toString();
|
||||
// Device CPU.
|
||||
cpu.clock = map.value(deviceClockKeyC).toString();
|
||||
cpu.core = map.value(deviceCoreKeyC).toString();
|
||||
cpu.fpu = map.value(deviceFpuKeyC).toString();
|
||||
cpu.mpu = map.value(deviceMpuKeyC).toString();
|
||||
// Device MEMORY.
|
||||
const QVariantList memoryList = map.value(deviceMemoryKeyC).toList();
|
||||
for (const auto &entry : memoryList) {
|
||||
const auto m = entry.toMap();
|
||||
DeviceSelection::Memory memory;
|
||||
memory.id = m.value(deviceMemoryIdKeyC).toString();
|
||||
memory.start = m.value(deviceMemoryStartKeyC).toString();
|
||||
memory.size = m.value(deviceMemorySizeKeyC).toString();
|
||||
memories.push_back(memory);
|
||||
}
|
||||
// Device ALGORITHM.
|
||||
algorithmIndex = map.value(deviceAlgorithmIndexKeyC).toInt();
|
||||
const QVariantList algorithmList = map.value(deviceAlgorithmKeyC).toList();
|
||||
for (const auto &entry : algorithmList) {
|
||||
const auto m = entry.toMap();
|
||||
DeviceSelection::Algorithm algorithm;
|
||||
algorithm.path = m.value(deviceAlgorithmPathKeyC).toString();
|
||||
algorithm.start = m.value(deviceAlgorithmStartKeyC).toString();
|
||||
algorithm.size = m.value(deviceAlgorithmSizeKeyC).toString();
|
||||
algorithms.push_back(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceSelection::Package::operator==(const Package &other) const
|
||||
{
|
||||
return desc == other.desc && file == other.file
|
||||
&& name == other.name && url == other.url
|
||||
&& vendor == other.vendor && version == other.version;
|
||||
}
|
||||
|
||||
bool DeviceSelection::Cpu::operator==(const Cpu &other) const
|
||||
{
|
||||
return core == other.core && clock == other.clock
|
||||
&& fpu == other.fpu && mpu == other.mpu;
|
||||
}
|
||||
|
||||
bool DeviceSelection::Memory::operator==(const Memory &other) const
|
||||
{
|
||||
return id == other.id && start == other.start && size == other.size;
|
||||
}
|
||||
|
||||
bool DeviceSelection::Algorithm::operator==(const Algorithm &other) const
|
||||
{
|
||||
return path == other.path && start == other.start && size == other.size;
|
||||
}
|
||||
|
||||
bool DeviceSelection::operator==(const DeviceSelection &other) const
|
||||
{
|
||||
return package == other.package && name == other.name && desc == other.desc
|
||||
&& family == other.family && subfamily == other.subfamily
|
||||
&& vendor == other.vendor && svd == other.svd && cpu == other.cpu
|
||||
&& memories == other.memories && algorithms == other.algorithms
|
||||
&& algorithmIndex == other.algorithmIndex;
|
||||
}
|
||||
|
||||
// DeviceSelectionMemoryItem
|
||||
|
||||
class DeviceSelectionMemoryItem final : public TreeItem
|
||||
{
|
||||
public:
|
||||
enum Column { IdColumn, StartColumn, SizeColumn};
|
||||
explicit DeviceSelectionMemoryItem(int index, DeviceSelection &selection)
|
||||
: m_index(index), m_selection(selection)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||
const auto &memory = m_selection.memories.at(m_index);
|
||||
switch (column) {
|
||||
case IdColumn: return memory.id;
|
||||
case StartColumn: return memory.start;
|
||||
case SizeColumn: return memory.size;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool setData(int column, const QVariant &data, int role) final
|
||||
{
|
||||
if (role == Qt::EditRole) {
|
||||
auto &memory = m_selection.memories.at(m_index);
|
||||
switch (column) {
|
||||
case StartColumn:
|
||||
memory.start = data.toString();
|
||||
return true;
|
||||
case SizeColumn:
|
||||
memory.size = data.toString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags(int column) const final
|
||||
{
|
||||
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
if (column == StartColumn || column == SizeColumn)
|
||||
flags |= Qt::ItemIsEditable;
|
||||
return flags;
|
||||
}
|
||||
|
||||
private:
|
||||
const int m_index;
|
||||
DeviceSelection &m_selection;
|
||||
};
|
||||
|
||||
// DeviceSelectionMemoryModel
|
||||
|
||||
DeviceSelectionMemoryModel::DeviceSelectionMemoryModel(DeviceSelection &selection, QObject *parent)
|
||||
: TreeModel<TreeItem, DeviceSelectionMemoryItem>(parent), m_selection(selection)
|
||||
{
|
||||
setHeader({tr("ID"), tr("Start"), tr("Size")});
|
||||
refresh();
|
||||
}
|
||||
|
||||
void DeviceSelectionMemoryModel::refresh()
|
||||
{
|
||||
clear();
|
||||
|
||||
const auto begin = m_selection.memories.begin();
|
||||
for (auto it = begin; it < m_selection.memories.end(); ++it) {
|
||||
const auto index = std::distance(begin, it);
|
||||
const auto item = new DeviceSelectionMemoryItem(index, m_selection);
|
||||
rootItem()->appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceSelectionMemoryView
|
||||
|
||||
DeviceSelectionMemoryView::DeviceSelectionMemoryView(DeviceSelection &selection, QWidget *parent)
|
||||
: TreeView(parent)
|
||||
{
|
||||
setRootIsDecorated(true);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
const auto model = new DeviceSelectionMemoryModel(selection, this);
|
||||
setModel(model);
|
||||
|
||||
connect(model, &DeviceSelectionMemoryModel::dataChanged,
|
||||
this, &DeviceSelectionMemoryView::memoryChanged);
|
||||
}
|
||||
|
||||
void DeviceSelectionMemoryView::refresh()
|
||||
{
|
||||
qobject_cast<DeviceSelectionMemoryModel *>(model())->refresh();
|
||||
}
|
||||
|
||||
// DeviceSelectionAlgorithmItem
|
||||
|
||||
class DeviceSelectionAlgorithmItem final : public TreeItem
|
||||
{
|
||||
public:
|
||||
enum Column { PathColumn, StartColumn, SizeColumn };
|
||||
explicit DeviceSelectionAlgorithmItem(int index, DeviceSelection &selection)
|
||||
: m_index(index), m_selection(selection)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||
const auto &algorithm = m_selection.algorithms.at(m_index);
|
||||
switch (column) {
|
||||
case PathColumn: return algorithm.path;
|
||||
case StartColumn: return algorithm.start;
|
||||
case SizeColumn: return algorithm.size;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool setData(int column, const QVariant &data, int role) final
|
||||
{
|
||||
if (role == Qt::EditRole) {
|
||||
auto &algorithm = m_selection.algorithms.at(m_index);
|
||||
switch (column) {
|
||||
case StartColumn:
|
||||
algorithm.start = data.toString();
|
||||
return true;
|
||||
case SizeColumn:
|
||||
algorithm.size = data.toString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags(int column) const final
|
||||
{
|
||||
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
if (column == StartColumn || column == SizeColumn)
|
||||
flags |= Qt::ItemIsEditable;
|
||||
return flags;
|
||||
}
|
||||
|
||||
private:
|
||||
const int m_index;
|
||||
DeviceSelection &m_selection;
|
||||
};
|
||||
|
||||
// DeviceSelectionAlgorithmModel
|
||||
|
||||
DeviceSelectionAlgorithmModel::DeviceSelectionAlgorithmModel(DeviceSelection &selection,
|
||||
QObject *parent)
|
||||
: TreeModel<TreeItem, DeviceSelectionAlgorithmItem>(parent), m_selection(selection)
|
||||
{
|
||||
setHeader({tr("Name"), tr("Start"), tr("Size")});
|
||||
refresh();
|
||||
}
|
||||
|
||||
void DeviceSelectionAlgorithmModel::refresh()
|
||||
{
|
||||
clear();
|
||||
|
||||
const auto begin = m_selection.algorithms.begin();
|
||||
for (auto it = begin; it < m_selection.algorithms.end(); ++it) {
|
||||
const auto index = std::distance(begin, it);
|
||||
const auto item = new DeviceSelectionAlgorithmItem(index, m_selection);
|
||||
rootItem()->appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceSelectionAlgorithmView
|
||||
|
||||
DeviceSelectionAlgorithmView::DeviceSelectionAlgorithmView(DeviceSelection &selection,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
const auto model = new DeviceSelectionAlgorithmModel(selection, this);
|
||||
const auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_comboBox = new QComboBox;
|
||||
m_comboBox->setToolTip(tr("Algorithm path."));
|
||||
m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_comboBox->setModel(model);
|
||||
layout->addWidget(m_comboBox);
|
||||
const auto startEdit = new QLineEdit;
|
||||
startEdit->setToolTip(tr("Start address."));
|
||||
layout->addWidget(startEdit);
|
||||
const auto sizeEdit = new QLineEdit;
|
||||
sizeEdit->setToolTip(tr("Size."));
|
||||
layout->addWidget(sizeEdit);
|
||||
setLayout(layout);
|
||||
|
||||
const auto mapper = new QDataWidgetMapper(this);
|
||||
mapper->setModel(model);
|
||||
mapper->addMapping(startEdit, DeviceSelectionAlgorithmItem::StartColumn);
|
||||
mapper->addMapping(sizeEdit, DeviceSelectionAlgorithmItem::SizeColumn);
|
||||
|
||||
connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, [mapper, this](int index) {
|
||||
mapper->setCurrentIndex(index);
|
||||
emit algorithmChanged(index);
|
||||
});
|
||||
|
||||
connect(model, &DeviceSelectionAlgorithmModel::dataChanged, this, [this]() {
|
||||
emit algorithmChanged(-1);
|
||||
});
|
||||
|
||||
connect(startEdit, &QLineEdit::editingFinished, mapper, &QDataWidgetMapper::submit);
|
||||
connect(sizeEdit, &QLineEdit::editingFinished, mapper, &QDataWidgetMapper::submit);
|
||||
}
|
||||
|
||||
void DeviceSelectionAlgorithmView::setAlgorithm(int index)
|
||||
{
|
||||
m_comboBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DeviceSelectionAlgorithmView::refresh()
|
||||
{
|
||||
const QSignalBlocker blocker(this);
|
||||
qobject_cast<DeviceSelectionAlgorithmModel *>(m_comboBox->model())->refresh();
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/basetreeview.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DeviceSelection
|
||||
|
||||
class DeviceSelection final
|
||||
{
|
||||
public:
|
||||
struct Package {
|
||||
QString desc;
|
||||
QString file;
|
||||
QString name;
|
||||
QString url;
|
||||
QString vendor;
|
||||
QString version;
|
||||
|
||||
bool operator==(const Package &other) const;
|
||||
};
|
||||
|
||||
struct Cpu {
|
||||
QString clock;
|
||||
QString core;
|
||||
QString fpu;
|
||||
QString mpu;
|
||||
|
||||
bool operator==(const Cpu &other) const;
|
||||
};
|
||||
|
||||
struct Memory {
|
||||
QString id;
|
||||
QString size;
|
||||
QString start;
|
||||
|
||||
bool operator==(const Memory &other) const;
|
||||
};
|
||||
using Memories = std::vector<Memory>;
|
||||
|
||||
struct Algorithm {
|
||||
QString path;
|
||||
QString size;
|
||||
QString start;
|
||||
|
||||
bool operator==(const Algorithm &other) const;
|
||||
};
|
||||
using Algorithms = std::vector<Algorithm>;
|
||||
|
||||
Package package;
|
||||
QString name;
|
||||
QString desc;
|
||||
QString family;
|
||||
QString subfamily;
|
||||
QString vendor;
|
||||
QString svd;
|
||||
Cpu cpu;
|
||||
Memories memories;
|
||||
Algorithms algorithms;
|
||||
int algorithmIndex = 0;
|
||||
|
||||
QVariantMap toMap() const;
|
||||
void fromMap(const QVariantMap &map);
|
||||
bool operator==(const DeviceSelection &other) const;
|
||||
};
|
||||
|
||||
// DeviceSelectionMemoryModel
|
||||
|
||||
class DeviceSelectionMemoryItem;
|
||||
class DeviceSelectionMemoryModel final
|
||||
: public Utils::TreeModel<Utils::TreeItem, DeviceSelectionMemoryItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionMemoryModel(DeviceSelection &selection, QObject *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
DeviceSelection &m_selection;
|
||||
};
|
||||
|
||||
// DeviceSelectionMemoryView
|
||||
|
||||
class DeviceSelectionMemoryView final : public Utils::TreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionMemoryView(DeviceSelection &selection, QWidget *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void memoryChanged();
|
||||
};
|
||||
|
||||
// DeviceSelectionAlgorithmModel
|
||||
|
||||
class DeviceSelectionAlgorithmItem;
|
||||
class DeviceSelectionAlgorithmModel final
|
||||
: public Utils::TreeModel<Utils::TreeItem, DeviceSelectionAlgorithmItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionAlgorithmModel(DeviceSelection &selection, QObject *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
DeviceSelection &m_selection;
|
||||
};
|
||||
|
||||
// DeviceSelectionAlgorithmView
|
||||
|
||||
class DeviceSelectionAlgorithmView final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionAlgorithmView(DeviceSelection &selection, QWidget *parent = nullptr);
|
||||
void setAlgorithm(int index);
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void algorithmChanged(int index = -1);
|
||||
|
||||
private:
|
||||
QComboBox *m_comboBox = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
|
||||
Q_DECLARE_METATYPE(BareMetal::Internal::Uv::DeviceSelection)
|
||||
@@ -0,0 +1,206 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h" // for targetUVisionPath()
|
||||
#include "uvtargetdevicemodel.h"
|
||||
#include "uvtargetdeviceviewer.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DeviceSelectorToolPanel
|
||||
|
||||
DeviceSelectorToolPanel::DeviceSelectorToolPanel(QWidget *parent)
|
||||
: FadingPanel(parent)
|
||||
{
|
||||
const auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
const auto button = new QPushButton(tr("Manage..."));
|
||||
layout->addWidget(button);
|
||||
setLayout(layout);
|
||||
connect(button, &QPushButton::clicked, this, &DeviceSelectorToolPanel::clicked);
|
||||
}
|
||||
|
||||
void DeviceSelectorToolPanel::fadeTo(qreal value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void DeviceSelectorToolPanel::setOpacity(qreal value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
// DeviceSelectorDetailsPanel
|
||||
|
||||
DeviceSelectorDetailsPanel::DeviceSelectorDetailsPanel(DeviceSelection &selection,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), m_selection(selection)
|
||||
{
|
||||
const auto layout = new QFormLayout;
|
||||
m_vendorEdit = new QLineEdit;
|
||||
m_vendorEdit->setReadOnly(true);
|
||||
layout->addRow(tr("Vendor:"), m_vendorEdit);
|
||||
m_fimilyEdit = new QLineEdit;;
|
||||
m_fimilyEdit->setReadOnly(true);
|
||||
layout->addRow(tr("Family:"), m_fimilyEdit);
|
||||
m_descEdit = new QPlainTextEdit;;
|
||||
m_descEdit->setReadOnly(true);
|
||||
layout->addRow(tr("Description:"), m_descEdit);
|
||||
m_memoryView = new DeviceSelectionMemoryView(m_selection);
|
||||
layout->addRow(tr("Memory:"), m_memoryView);
|
||||
m_algorithmView = new DeviceSelectionAlgorithmView(m_selection);
|
||||
layout->addRow(tr("Flash algorithm"), m_algorithmView);
|
||||
setLayout(layout);
|
||||
|
||||
refresh();
|
||||
|
||||
connect(m_memoryView, &DeviceSelectionMemoryView::memoryChanged,
|
||||
this, &DeviceSelectorDetailsPanel::selectionChanged);
|
||||
connect(m_algorithmView, &DeviceSelectionAlgorithmView::algorithmChanged,
|
||||
this, [this](int index) {
|
||||
if (index >= 0)
|
||||
m_selection.algorithmIndex = index;
|
||||
emit selectionChanged();
|
||||
});
|
||||
}
|
||||
|
||||
static QString trimVendor(const QString &vendor)
|
||||
{
|
||||
const int colonIndex = vendor.lastIndexOf(':');
|
||||
return vendor.mid(0, colonIndex);
|
||||
}
|
||||
|
||||
void DeviceSelectorDetailsPanel::refresh()
|
||||
{
|
||||
m_vendorEdit->setText(trimVendor(m_selection.vendor));
|
||||
m_fimilyEdit->setText(m_selection.family);
|
||||
m_descEdit->setPlainText(m_selection.desc);
|
||||
m_memoryView->refresh();
|
||||
m_algorithmView->refresh();
|
||||
m_algorithmView->setAlgorithm(m_selection.algorithmIndex);
|
||||
}
|
||||
|
||||
// DeviceSelector
|
||||
|
||||
DeviceSelector::DeviceSelector(QWidget *parent)
|
||||
: DetailsWidget(parent)
|
||||
{
|
||||
const auto toolPanel = new DeviceSelectorToolPanel;
|
||||
setToolWidget(toolPanel);
|
||||
const auto detailsPanel = new DeviceSelectorDetailsPanel(m_selection);
|
||||
setWidget(detailsPanel);
|
||||
|
||||
connect(toolPanel, &DeviceSelectorToolPanel::clicked, this, [this]() {
|
||||
const QString uVisionPath = targetUVisionPath();
|
||||
if (uVisionPath.isEmpty()) {
|
||||
QMessageBox::warning(this,
|
||||
tr("uVision path not found"),
|
||||
tr("Please open a configured project before\n"
|
||||
"the target device selection."),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
DeviceSelectionDialog dialog(uVisionPath, this);
|
||||
const int result = dialog.exec();
|
||||
if (result != QDialog::Accepted)
|
||||
return;
|
||||
DeviceSelection selection;
|
||||
selection = dialog.selection();
|
||||
setSelection(selection);
|
||||
}
|
||||
});
|
||||
|
||||
connect(detailsPanel, &DeviceSelectorDetailsPanel::selectionChanged,
|
||||
this, &DeviceSelector::selectionChanged);
|
||||
}
|
||||
|
||||
void DeviceSelector::setSelection(const DeviceSelection &selection)
|
||||
{
|
||||
m_selection = selection;
|
||||
const auto summary = m_selection.name.isEmpty()
|
||||
? tr("Target device not selected.") : m_selection.name;
|
||||
setSummaryText(summary);
|
||||
setExpandable(!m_selection.name.isEmpty());
|
||||
|
||||
if (const auto detailsPanel = qobject_cast<DeviceSelectorDetailsPanel *>(widget()))
|
||||
detailsPanel->refresh();
|
||||
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
DeviceSelection DeviceSelector::selection() const
|
||||
{
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
// DeviceSelectionDialog
|
||||
|
||||
DeviceSelectionDialog::DeviceSelectionDialog(const QString &uVisionPath, QWidget *parent)
|
||||
: QDialog(parent), m_model(new DeviceSelectionModel(this)), m_view(new DeviceSelectionView(this))
|
||||
{
|
||||
setWindowTitle(tr("Available target devices"));
|
||||
|
||||
const auto layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(m_view);
|
||||
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
layout->addWidget(buttonBox);
|
||||
setLayout(layout);
|
||||
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DeviceSelectionDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &DeviceSelectionDialog::reject);
|
||||
|
||||
connect(m_view, &DeviceSelectionView::deviceSelected, this,
|
||||
[this](const DeviceSelection &selection) {
|
||||
m_selection = selection;
|
||||
});
|
||||
|
||||
m_model->fillAllPacks(uVisionPath);
|
||||
m_view->setModel(m_model);
|
||||
}
|
||||
|
||||
void DeviceSelectionDialog::setSelection(const DeviceSelection &selection)
|
||||
{
|
||||
m_selection = selection;
|
||||
}
|
||||
|
||||
DeviceSelection DeviceSelectionDialog::selection() const
|
||||
{
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,127 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvtargetdeviceselection.h"
|
||||
|
||||
#include <utils/detailsbutton.h>
|
||||
#include <utils/detailswidget.h>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLineEdit;
|
||||
class QPlainTextEdit;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
class DeviceSelectionModel;
|
||||
class DeviceSelectionView;
|
||||
class DeviceSelectionMemoryView;
|
||||
class DeviceSelectionAlgorithmView;
|
||||
|
||||
// DeviceSelector
|
||||
|
||||
class DeviceSelector final : public Utils::DetailsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelector(QWidget *parent = nullptr);
|
||||
|
||||
void setSelection(const DeviceSelection &selection);
|
||||
DeviceSelection selection() const;
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
DeviceSelection m_selection;
|
||||
};
|
||||
|
||||
// DeviceSelectorToolPanel
|
||||
|
||||
class DeviceSelectorToolPanel final : public Utils::FadingPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectorToolPanel(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
private:
|
||||
void fadeTo(qreal value) final;
|
||||
void setOpacity(qreal value) final;
|
||||
};
|
||||
|
||||
// DeviceSelectorDetailsPanel
|
||||
|
||||
class DeviceSelectorDetailsPanel final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectorDetailsPanel(DeviceSelection &selection, QWidget *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
DeviceSelection &m_selection;
|
||||
QLineEdit *m_vendorEdit = nullptr;
|
||||
QLineEdit *m_fimilyEdit = nullptr;
|
||||
QPlainTextEdit *m_descEdit = nullptr;
|
||||
DeviceSelectionMemoryView *m_memoryView = nullptr;
|
||||
DeviceSelectionAlgorithmView *m_algorithmView = nullptr;
|
||||
};
|
||||
|
||||
// DeviceSelectionDialog
|
||||
|
||||
class DeviceSelectionDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceSelectionDialog(const QString &uVisionPath, QWidget *parent = nullptr);
|
||||
DeviceSelection selection() const;
|
||||
|
||||
private:
|
||||
void setSelection(const DeviceSelection &selection);
|
||||
|
||||
DeviceSelection m_selection;
|
||||
DeviceSelectionModel *m_model = nullptr;
|
||||
DeviceSelectionView *m_view = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,209 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h" // for toolsFilePath()
|
||||
#include "uvtargetdrivermodel.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
constexpr char cpuDllKey[] = "CPUDLL";
|
||||
constexpr char driverKey[] = "TDRV";
|
||||
|
||||
struct Dll
|
||||
{
|
||||
int index = -1;
|
||||
QString mnemonic;
|
||||
QString path;
|
||||
QString content;
|
||||
};
|
||||
using Dlls = std::vector<Dll>;
|
||||
|
||||
// Parse the lines in a forms like:
|
||||
// "CPUDLL0=SARM.DLL(TDRV16,TDRV17,TDRV18)"
|
||||
// "TDRV1=BIN\ULP2CM3.DLL("ULINK Pro Cortex Debugger")"
|
||||
static Dll extractDll(const QString &line, const QString &pattern)
|
||||
{
|
||||
const int equalIndex = line.indexOf('=');
|
||||
const int leftBracketIndex = line.indexOf('(', equalIndex + 1);
|
||||
const int rightBracketIndex = line.indexOf(')', leftBracketIndex + 1);
|
||||
if (equalIndex < 0 || leftBracketIndex < 0 || rightBracketIndex < 0)
|
||||
return {};
|
||||
|
||||
Dll dll;
|
||||
dll.index = line.mid(pattern.size(), equalIndex - pattern.size()).toInt();
|
||||
dll.mnemonic = line.mid(0, equalIndex).trimmed();
|
||||
dll.path = line.mid(equalIndex + 1, leftBracketIndex - equalIndex - 1).trimmed();
|
||||
dll.content = line.mid(leftBracketIndex + 1,
|
||||
rightBracketIndex - leftBracketIndex - 1).trimmed();
|
||||
return dll;
|
||||
}
|
||||
|
||||
static bool collectCpuDllsAndDrivers(QIODevice *file, Dlls &allCpuDlls, Dlls &allDrivers)
|
||||
{
|
||||
QTextStream in(file);
|
||||
bool armadsFound = false;
|
||||
while (!in.atEnd()) {
|
||||
const QString line = in.readLine().trimmed();
|
||||
if (!armadsFound) {
|
||||
if (line == "[ARMADS]")
|
||||
armadsFound = true;
|
||||
} else if (line.startsWith('[') && line.endsWith(']')) {
|
||||
break;
|
||||
} else if (line.startsWith(cpuDllKey)) {
|
||||
const Dll dll = extractDll(line, cpuDllKey);
|
||||
if (dll.index >= 0)
|
||||
allCpuDlls.push_back(dll);
|
||||
} else if (line.startsWith(driverKey)) {
|
||||
const Dll dll = extractDll(line, driverKey);
|
||||
if (dll.index >= 0)
|
||||
allDrivers.push_back(dll);
|
||||
}
|
||||
}
|
||||
return armadsFound;
|
||||
}
|
||||
|
||||
// DriverSelectionItem
|
||||
|
||||
class DriverSelectionItem final : public TreeItem
|
||||
{
|
||||
public:
|
||||
enum Column { PathColumn };
|
||||
explicit DriverSelectionItem(int index = -1)
|
||||
: m_index(index)
|
||||
{}
|
||||
|
||||
DriverSelection toSelection() const
|
||||
{
|
||||
DriverSelection selection;
|
||||
selection.index = m_index;
|
||||
selection.dll = m_dll;
|
||||
selection.name = m_name;
|
||||
selection.cpuDlls = m_cpuDlls;
|
||||
return selection;
|
||||
}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole && column == PathColumn)
|
||||
return m_name;
|
||||
return {};
|
||||
}
|
||||
|
||||
const int m_index;
|
||||
QString m_name;
|
||||
QString m_dll;
|
||||
QStringList m_cpuDlls;
|
||||
};
|
||||
|
||||
// DriverSelectionModel
|
||||
|
||||
DriverSelectionModel::DriverSelectionModel(QObject *parent)
|
||||
: TreeModel<DriverSelectionItem>(parent)
|
||||
{
|
||||
setHeader({tr("Path")});
|
||||
}
|
||||
|
||||
void DriverSelectionModel::fillDrivers(const QString &uVisionFilePath,
|
||||
const QStringList &supportedDrivers)
|
||||
{
|
||||
clear();
|
||||
|
||||
QFile f(toolsFilePath(uVisionFilePath));
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
return;
|
||||
|
||||
Dlls allCpuDlls;
|
||||
Dlls allDrivers;
|
||||
if (!collectCpuDllsAndDrivers(&f, allCpuDlls, allDrivers))
|
||||
return;
|
||||
|
||||
for (const Dll &dll : qAsConst(allDrivers)) {
|
||||
if (!supportedDrivers.contains(dll.path))
|
||||
continue;
|
||||
const auto item = new DriverSelectionItem(dll.index);
|
||||
item->m_dll = dll.path;
|
||||
item->m_name = dll.content;
|
||||
for (const Dll &cpu : qAsConst(allCpuDlls)) {
|
||||
const QStringList mnemonics = cpu.content.split(',');
|
||||
if (mnemonics.contains(dll.mnemonic))
|
||||
item->m_cpuDlls.push_back(cpu.path);
|
||||
}
|
||||
rootItem()->appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// DriverSelectionView
|
||||
|
||||
DriverSelectionView::DriverSelectionView(QWidget *parent)
|
||||
: TreeView(parent)
|
||||
{
|
||||
setRootIsDecorated(true);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
}
|
||||
|
||||
void DriverSelectionView::setCurrentSelection(const QString &driverDll)
|
||||
{
|
||||
const auto selectionModel = qobject_cast<DriverSelectionModel *>(model());
|
||||
if (!selectionModel)
|
||||
return;
|
||||
|
||||
const DriverSelectionItem *item = selectionModel->findNonRootItem(
|
||||
[driverDll](const DriverSelectionItem *item) {
|
||||
return item->m_dll == driverDll;
|
||||
});
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
const QModelIndex index = selectionModel->indexForItem(item);
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DriverSelectionView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
Q_UNUSED(previous)
|
||||
|
||||
if (!current.isValid())
|
||||
return;
|
||||
const auto selectionModel = qobject_cast<DriverSelectionModel *>(model());
|
||||
if (!selectionModel)
|
||||
return;
|
||||
const DriverSelectionItem *item = selectionModel->itemForIndex(current);
|
||||
if (!item)
|
||||
return;
|
||||
const auto selection = item->toSelection();
|
||||
if (selection.index >= 0)
|
||||
emit driverSelected(selection);
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvtargetdriverselection.h"
|
||||
|
||||
#include <utils/basetreeview.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DriverSelectionModel
|
||||
|
||||
class DriverSelectionItem;
|
||||
class DriverSelectionModel final : public Utils::TreeModel<DriverSelectionItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectionModel(QObject *parent = nullptr);
|
||||
void fillDrivers(const QString &uVisionFilePath, const QStringList &supportedDrivers);
|
||||
};
|
||||
|
||||
// DriverSelectionView
|
||||
|
||||
class DriverSelectionView final : public Utils::TreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DriverSelectionView(QWidget *parent = nullptr);
|
||||
void setCurrentSelection(const QString &driverDll);
|
||||
|
||||
signals:
|
||||
void driverSelected(const DriverSelection &selection);
|
||||
|
||||
private:
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) final;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,152 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvtargetdriverselection.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// Driver data keys.
|
||||
constexpr char driverIndexKeyC[] = "BareMetal.UvscServerProvider.DriverIndex";
|
||||
constexpr char driverCpuDllIndexKeyC[] = "BareMetal.UvscServerProvider.DriverCpuDllIndex";
|
||||
constexpr char driverDllKeyC[] = "BareMetal.UvscServerProvider.DriverDll";
|
||||
constexpr char driverCpuDllsKeyC[] = "BareMetal.UvscServerProvider.DriverCpuDlls";
|
||||
constexpr char driverNameKeyC[] = "BareMetal.UvscServerProvider.DriverName";
|
||||
|
||||
// DriverSelection
|
||||
|
||||
QVariantMap DriverSelection::toMap() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert(driverIndexKeyC, index);
|
||||
map.insert(driverCpuDllIndexKeyC, cpuDllIndex);
|
||||
map.insert(driverDllKeyC, dll);
|
||||
map.insert(driverCpuDllsKeyC, cpuDlls);
|
||||
map.insert(driverNameKeyC, name);
|
||||
return map;
|
||||
}
|
||||
|
||||
void DriverSelection::fromMap(const QVariantMap &map)
|
||||
{
|
||||
index = map.value(driverIndexKeyC).toInt();
|
||||
cpuDllIndex = map.value(driverCpuDllIndexKeyC).toInt();
|
||||
dll = map.value(driverDllKeyC).toString();
|
||||
cpuDlls = map.value(driverCpuDllsKeyC).toStringList();
|
||||
name = map.value(driverNameKeyC).toString();
|
||||
}
|
||||
|
||||
bool DriverSelection::operator==(const DriverSelection &other) const
|
||||
{
|
||||
return index == other.index && cpuDllIndex == other.cpuDllIndex
|
||||
&& dll == other.dll && cpuDlls == other.cpuDlls && name == other.name;
|
||||
}
|
||||
|
||||
// DriverSelectionCpuDllItem
|
||||
|
||||
class DriverSelectionCpuDllItem final : public TreeItem
|
||||
{
|
||||
public:
|
||||
enum Column { DllNameColumn };
|
||||
explicit DriverSelectionCpuDllItem(int index, DriverSelection &selection)
|
||||
: m_index(index), m_selection(selection)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const final
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
const auto &dll = m_selection.cpuDlls.at(m_index);
|
||||
switch (column) {
|
||||
case DllNameColumn: return dll;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
const int m_index;
|
||||
DriverSelection &m_selection;
|
||||
};
|
||||
|
||||
// DriverSelectionCpuDllModel
|
||||
|
||||
DriverSelectionCpuDllModel::DriverSelectionCpuDllModel(DriverSelection &selection, QObject *parent)
|
||||
: TreeModel<TreeItem, DriverSelectionCpuDllItem>(parent), m_selection(selection)
|
||||
{
|
||||
setHeader({tr("Name")});
|
||||
refresh();
|
||||
}
|
||||
|
||||
void DriverSelectionCpuDllModel::refresh()
|
||||
{
|
||||
clear();
|
||||
|
||||
const auto begin = m_selection.cpuDlls.begin();
|
||||
for (auto it = begin; it < m_selection.cpuDlls.end(); ++it) {
|
||||
const auto index = std::distance(begin, it);
|
||||
const auto item = new DriverSelectionCpuDllItem(index, m_selection);
|
||||
rootItem()->appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
// DriverSelectionCpuDllView
|
||||
|
||||
DriverSelectionCpuDllView::DriverSelectionCpuDllView(DriverSelection &selection, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
const auto model = new DriverSelectionCpuDllModel(selection, this);
|
||||
const auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_comboBox = new QComboBox;
|
||||
m_comboBox->setToolTip(tr("Debugger CPU library (depends on a CPU core."));
|
||||
m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_comboBox->setModel(model);
|
||||
layout->addWidget(m_comboBox);
|
||||
setLayout(layout);
|
||||
|
||||
connect(m_comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &DriverSelectionCpuDllView::dllChanged);
|
||||
}
|
||||
|
||||
void DriverSelectionCpuDllView::setCpuDll(int index)
|
||||
{
|
||||
m_comboBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DriverSelectionCpuDllView::refresh()
|
||||
{
|
||||
const QSignalBlocker blocker(this);
|
||||
qobject_cast<DriverSelectionCpuDllModel *>(m_comboBox->model())->refresh();
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/basetreeview.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DriverSelection
|
||||
|
||||
class DriverSelection final
|
||||
{
|
||||
public:
|
||||
QString name;
|
||||
QString dll;
|
||||
QStringList cpuDlls;
|
||||
int index = 0;
|
||||
int cpuDllIndex = 0;
|
||||
|
||||
QVariantMap toMap() const;
|
||||
void fromMap(const QVariantMap &map);
|
||||
|
||||
bool operator==(const DriverSelection &other) const;
|
||||
};
|
||||
|
||||
// DriverSelectionCpuDllModel
|
||||
|
||||
class DriverSelectionCpuDllItem;
|
||||
class DriverSelectionCpuDllModel final
|
||||
: public Utils::TreeModel<Utils::TreeItem, DriverSelectionCpuDllItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectionCpuDllModel(DriverSelection &selection, QObject *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
DriverSelection &m_selection;
|
||||
};
|
||||
|
||||
// DriverSelectionCpuDllView
|
||||
|
||||
class DriverSelectionCpuDllView final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectionCpuDllView(DriverSelection &selection, QWidget *parent = nullptr);
|
||||
void setCpuDll(int index);
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void dllChanged(int index = -1);
|
||||
|
||||
private:
|
||||
QComboBox *m_comboBox = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
|
||||
Q_DECLARE_METATYPE(BareMetal::Internal::Uv::DriverSelection)
|
||||
@@ -0,0 +1,190 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvproject.h" // for targetUVisionPath()
|
||||
#include "uvtargetdrivermodel.h"
|
||||
#include "uvtargetdriverviewer.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
// DriverSelectorToolPanel
|
||||
|
||||
DriverSelectorToolPanel::DriverSelectorToolPanel(QWidget *parent)
|
||||
: FadingPanel(parent)
|
||||
{
|
||||
const auto layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
const auto button = new QPushButton(tr("Manage..."));
|
||||
layout->addWidget(button);
|
||||
setLayout(layout);
|
||||
connect(button, &QPushButton::clicked, this, &DriverSelectorToolPanel::clicked);
|
||||
}
|
||||
|
||||
void DriverSelectorToolPanel::fadeTo(qreal value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void DriverSelectorToolPanel::setOpacity(qreal value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
// DriverSelectorDetailsPanel
|
||||
|
||||
DriverSelectorDetailsPanel::DriverSelectorDetailsPanel(DriverSelection &selection, QWidget *parent)
|
||||
: QWidget(parent), m_selection(selection)
|
||||
{
|
||||
const auto layout = new QFormLayout;
|
||||
m_dllEdit = new QLineEdit;;
|
||||
m_dllEdit->setReadOnly(true);
|
||||
m_dllEdit->setToolTip(tr("Debugger driver library"));
|
||||
layout->addRow(tr("Driver library:"), m_dllEdit);
|
||||
m_cpuDllView = new DriverSelectionCpuDllView(m_selection);
|
||||
layout->addRow(tr("CPU library:"), m_cpuDllView);
|
||||
setLayout(layout);
|
||||
|
||||
refresh();
|
||||
|
||||
connect(m_cpuDllView, &DriverSelectionCpuDllView::dllChanged, this, [this](int index) {
|
||||
if (index >= 0)
|
||||
m_selection.cpuDllIndex = index;
|
||||
emit selectionChanged();
|
||||
});
|
||||
}
|
||||
|
||||
void DriverSelectorDetailsPanel::refresh()
|
||||
{
|
||||
m_dllEdit->setText((m_selection.dll));
|
||||
m_cpuDllView->refresh();
|
||||
m_cpuDllView->setCpuDll(m_selection.cpuDllIndex);
|
||||
}
|
||||
|
||||
// DriverSelector
|
||||
|
||||
DriverSelector::DriverSelector(const QStringList &supportedDrivers, QWidget *parent)
|
||||
: DetailsWidget(parent)
|
||||
{
|
||||
const auto toolPanel = new DriverSelectorToolPanel;
|
||||
toolPanel->setEnabled(!supportedDrivers.isEmpty());
|
||||
setToolWidget(toolPanel);
|
||||
const auto detailsPanel = new DriverSelectorDetailsPanel(m_selection);
|
||||
setWidget(detailsPanel);
|
||||
|
||||
connect(toolPanel, &DriverSelectorToolPanel::clicked, this, [=]() {
|
||||
const QString uVisionPath = targetUVisionPath();
|
||||
if (uVisionPath.isEmpty()) {
|
||||
QMessageBox::warning(this,
|
||||
tr("uVision path not found"),
|
||||
tr("Please open a configured project before\n"
|
||||
"the target driver selection."),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
DriverSelectionDialog dialog(uVisionPath, supportedDrivers, this);
|
||||
const int result = dialog.exec();
|
||||
if (result != QDialog::Accepted)
|
||||
return;
|
||||
DriverSelection selection;
|
||||
selection = dialog.selection();
|
||||
setSelection(selection);
|
||||
}
|
||||
});
|
||||
|
||||
connect(detailsPanel, &DriverSelectorDetailsPanel::selectionChanged,
|
||||
this, &DriverSelector::selectionChanged);
|
||||
}
|
||||
|
||||
void DriverSelector::setSelection(const DriverSelection &selection)
|
||||
{
|
||||
m_selection = selection;
|
||||
const auto summary = m_selection.name.isEmpty()
|
||||
? tr("Target driver not selected.") : m_selection.name;
|
||||
setSummaryText(summary);
|
||||
setExpandable(!m_selection.name.isEmpty());
|
||||
|
||||
if (const auto detailsPanel = qobject_cast<DriverSelectorDetailsPanel *>(widget()))
|
||||
detailsPanel->refresh();
|
||||
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
DriverSelection DriverSelector::selection() const
|
||||
{
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
// DriverSelectionDialog
|
||||
|
||||
DriverSelectionDialog::DriverSelectionDialog(const QString &uVisionPath,
|
||||
const QStringList &supportedDrivers,
|
||||
QWidget *parent)
|
||||
: QDialog(parent), m_model(new DriverSelectionModel(this)),
|
||||
m_view(new DriverSelectionView(this))
|
||||
{
|
||||
setWindowTitle(tr("Available target drivers"));
|
||||
|
||||
const auto layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(m_view);
|
||||
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
layout->addWidget(buttonBox);
|
||||
setLayout(layout);
|
||||
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &DriverSelectionDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &DriverSelectionDialog::reject);
|
||||
|
||||
connect(m_view, &DriverSelectionView::driverSelected, this,
|
||||
[this](const DriverSelection &selection) {
|
||||
m_selection = selection;
|
||||
});
|
||||
|
||||
m_model->fillDrivers(uVisionPath, supportedDrivers);
|
||||
m_view->setModel(m_model);
|
||||
}
|
||||
|
||||
void DriverSelectionDialog::setSelection(const DriverSelection &selection)
|
||||
{
|
||||
m_selection = selection;
|
||||
}
|
||||
|
||||
DriverSelection DriverSelectionDialog::selection() const
|
||||
{
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,123 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvtargetdriverselection.h"
|
||||
|
||||
#include <utils/detailsbutton.h>
|
||||
#include <utils/detailswidget.h>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLineEdit;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
namespace Uv {
|
||||
|
||||
class DriverSelectionModel;
|
||||
class DriverSelectionView;
|
||||
class DriverSelectionCpuDllView;
|
||||
|
||||
// DriverSelector
|
||||
|
||||
class DriverSelector final : public Utils::DetailsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelector(const QStringList &supportedDrivers, QWidget *parent = nullptr);
|
||||
void setSelection(const DriverSelection &selection);
|
||||
DriverSelection selection() const;
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
DriverSelection m_selection;
|
||||
};
|
||||
|
||||
// DriverSelectorToolPanel
|
||||
|
||||
class DriverSelectorToolPanel final : public Utils::FadingPanel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectorToolPanel(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
private:
|
||||
void fadeTo(qreal value) final;
|
||||
void setOpacity(qreal value) final;
|
||||
};
|
||||
|
||||
// DriverSelectorDetailsPanel
|
||||
|
||||
class DriverSelectorDetailsPanel final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectorDetailsPanel(DriverSelection &selection, QWidget *parent = nullptr);
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
DriverSelection &m_selection;
|
||||
QLineEdit *m_dllEdit = nullptr;
|
||||
DriverSelectionCpuDllView *m_cpuDllView = nullptr;
|
||||
};
|
||||
|
||||
// DriverSelectionDialog
|
||||
|
||||
class DriverSelectionDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DriverSelectionDialog(const QString &uVisionPath,
|
||||
const QStringList &supportedDrivers,
|
||||
QWidget *parent = nullptr);
|
||||
DriverSelection selection() const;
|
||||
|
||||
private:
|
||||
void setSelection(const DriverSelection &selection);
|
||||
|
||||
DriverSelection m_selection;
|
||||
DriverSelectionModel *m_model = nullptr;
|
||||
DriverSelectionView *m_view = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Uv
|
||||
} // namespace Internal
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QXmlStreamAttribute>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
class Project;
|
||||
class ProjectOptions;
|
||||
class Property;
|
||||
class PropertyGroup;
|
||||
|
||||
class INodeVisitor
|
||||
{
|
||||
public:
|
||||
virtual ~INodeVisitor() {}
|
||||
|
||||
virtual void visitProjectOptionsStart(const ProjectOptions *projectOptions)
|
||||
{ Q_UNUSED(projectOptions) }
|
||||
virtual void visitProjectOptionsEnd(const ProjectOptions *projectOptions)
|
||||
{ Q_UNUSED(projectOptions) }
|
||||
|
||||
virtual void visitProjectStart(const Project *project) { Q_UNUSED(project) }
|
||||
virtual void visitProjectEnd(const Project *project) { Q_UNUSED(project) }
|
||||
|
||||
virtual void visitPropertyStart(const Property *property) = 0;
|
||||
virtual void visitPropertyEnd(const Property *property) = 0;
|
||||
|
||||
virtual void visitPropertyGroupStart(const PropertyGroup *propertyGroup) = 0;
|
||||
virtual void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) = 0;
|
||||
};
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "xmlnodevisitor.h"
|
||||
#include "xmlproject.h"
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
// Project
|
||||
|
||||
void Project::accept(INodeVisitor *visitor) const
|
||||
{
|
||||
visitor->visitProjectStart(this);
|
||||
|
||||
for (const auto &child : children())
|
||||
child->accept(visitor);
|
||||
|
||||
visitor->visitProjectEnd(this);
|
||||
}
|
||||
|
||||
// ProjectOptions
|
||||
|
||||
void ProjectOptions::accept(INodeVisitor *visitor) const
|
||||
{
|
||||
visitor->visitProjectOptionsStart(this);
|
||||
|
||||
for (const auto &child : children())
|
||||
child->accept(visitor);
|
||||
|
||||
visitor->visitProjectOptionsEnd(this);
|
||||
}
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlproperty.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
// Project
|
||||
|
||||
class Project : public Property
|
||||
{
|
||||
public:
|
||||
void accept(INodeVisitor *visitor) const final;
|
||||
};
|
||||
|
||||
// ProjectOptions
|
||||
|
||||
class ProjectOptions : public Property
|
||||
{
|
||||
public:
|
||||
void accept(INodeVisitor *visitor) const final;
|
||||
};
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "xmlproject.h"
|
||||
#include "xmlprojectwriter.h"
|
||||
#include "xmlproperty.h"
|
||||
#include "xmlpropertygroup.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
// ProjectWriter
|
||||
|
||||
ProjectWriter::ProjectWriter(std::ostream *device)
|
||||
: m_device(device)
|
||||
{
|
||||
m_writer.reset(new QXmlStreamWriter(&m_buffer));
|
||||
m_writer->setAutoFormatting(true);
|
||||
m_writer->setAutoFormattingIndent(2);
|
||||
}
|
||||
|
||||
bool ProjectWriter::write(const Project *project)
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_writer->writeStartDocument();
|
||||
project->accept(this);
|
||||
m_writer->writeEndDocument();
|
||||
if (m_writer->hasError())
|
||||
return false;
|
||||
m_device->write(&*std::cbegin(m_buffer), m_buffer.size());
|
||||
return m_device->good();
|
||||
}
|
||||
|
||||
void ProjectWriter::visitPropertyStart(const Property *property)
|
||||
{
|
||||
const QString value = property->value().toString();
|
||||
const QString name = QString::fromUtf8(property->name());
|
||||
m_writer->writeTextElement(name, value);
|
||||
}
|
||||
|
||||
void ProjectWriter::visitPropertyEnd(const Property *property)
|
||||
{
|
||||
Q_UNUSED(property)
|
||||
}
|
||||
|
||||
void ProjectWriter::visitPropertyGroupStart(const PropertyGroup *propertyGroup)
|
||||
{
|
||||
const QString name = QString::fromUtf8(propertyGroup->name());
|
||||
m_writer->writeStartElement(name);
|
||||
}
|
||||
|
||||
void ProjectWriter::visitPropertyGroupEnd(const PropertyGroup *propertyGroup)
|
||||
{
|
||||
Q_UNUSED(propertyGroup)
|
||||
m_writer->writeEndElement();
|
||||
}
|
||||
|
||||
QXmlStreamWriter *ProjectWriter::writer() const
|
||||
{
|
||||
return m_writer.get();
|
||||
}
|
||||
|
||||
// ProjectOptionsWriter
|
||||
|
||||
ProjectOptionsWriter::ProjectOptionsWriter(std::ostream *device)
|
||||
: m_device(device)
|
||||
{
|
||||
m_writer.reset(new QXmlStreamWriter(&m_buffer));
|
||||
m_writer->setAutoFormatting(true);
|
||||
m_writer->setAutoFormattingIndent(2);
|
||||
}
|
||||
|
||||
bool ProjectOptionsWriter::write(const ProjectOptions *projectOptions)
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_writer->writeStartDocument();
|
||||
projectOptions->accept(this);
|
||||
m_writer->writeEndDocument();
|
||||
if (m_writer->hasError())
|
||||
return false;
|
||||
m_device->write(&*std::cbegin(m_buffer), m_buffer.size());
|
||||
return m_device->good();
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitPropertyStart(const Property *property)
|
||||
{
|
||||
const QString value = property->value().toString();
|
||||
const QString name = QString::fromUtf8(property->name());
|
||||
m_writer->writeTextElement(name, value);
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitPropertyEnd(const Property *property)
|
||||
{
|
||||
Q_UNUSED(property)
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitPropertyGroupStart(const PropertyGroup *propertyGroup)
|
||||
{
|
||||
const QString name = QString::fromUtf8(propertyGroup->name());
|
||||
m_writer->writeStartElement(name);
|
||||
}
|
||||
|
||||
void ProjectOptionsWriter::visitPropertyGroupEnd(const PropertyGroup *propertyGroup)
|
||||
{
|
||||
Q_UNUSED(propertyGroup)
|
||||
m_writer->writeEndElement();
|
||||
}
|
||||
|
||||
QXmlStreamWriter *ProjectOptionsWriter::writer() const
|
||||
{
|
||||
return m_writer.get();
|
||||
}
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlnodevisitor.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
// ProjectWriter
|
||||
|
||||
class ProjectWriter : public INodeVisitor
|
||||
{
|
||||
Q_DISABLE_COPY(ProjectWriter)
|
||||
public:
|
||||
explicit ProjectWriter(std::ostream *device);
|
||||
bool write(const Project *project);
|
||||
|
||||
protected:
|
||||
QXmlStreamWriter *writer() const;
|
||||
|
||||
private:
|
||||
void visitPropertyStart(const Property *property) final;
|
||||
void visitPropertyEnd(const Property *property) final;
|
||||
|
||||
void visitPropertyGroupStart(const PropertyGroup *propertyGroup) final;
|
||||
void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) final;
|
||||
|
||||
std::ostream *m_device = nullptr;
|
||||
QByteArray m_buffer;
|
||||
std::unique_ptr<QXmlStreamWriter> m_writer;
|
||||
};
|
||||
|
||||
// ProjectOptionsWriter
|
||||
|
||||
class ProjectOptionsWriter : public INodeVisitor
|
||||
{
|
||||
Q_DISABLE_COPY(ProjectOptionsWriter)
|
||||
public:
|
||||
explicit ProjectOptionsWriter(std::ostream *device);
|
||||
bool write(const ProjectOptions *projectOptions);
|
||||
|
||||
protected:
|
||||
QXmlStreamWriter *writer() const;
|
||||
|
||||
private:
|
||||
void visitPropertyStart(const Property *property) final;
|
||||
void visitPropertyEnd(const Property *property) final;
|
||||
|
||||
void visitPropertyGroupStart(const PropertyGroup *propertyGroup) final;
|
||||
void visitPropertyGroupEnd(const PropertyGroup *propertyGroup) final;
|
||||
|
||||
std::ostream *m_device = nullptr;
|
||||
QByteArray m_buffer;
|
||||
std::unique_ptr<QXmlStreamWriter> m_writer;
|
||||
};
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "xmlnodevisitor.h"
|
||||
#include "xmlproperty.h"
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
Property::Property(QByteArray name, QVariant value)
|
||||
{
|
||||
setName(std::move(name));
|
||||
setValue(std::move(value));
|
||||
}
|
||||
|
||||
void Property::appendProperty(QByteArray name, QVariant value)
|
||||
{
|
||||
appendChild<Property>(std::move(name), std::move(value));
|
||||
}
|
||||
|
||||
void Property::appendMultiLineProperty(QByteArray key, QStringList values, QChar sep)
|
||||
{
|
||||
const QString line = values.join(std::move(sep));
|
||||
appendProperty(std::move(key), QVariant::fromValue(line));
|
||||
}
|
||||
|
||||
void Property::accept(INodeVisitor *visitor) const
|
||||
{
|
||||
visitor->visitPropertyStart(this);
|
||||
|
||||
for (const auto &child : children())
|
||||
child->accept(visitor);
|
||||
|
||||
visitor->visitPropertyEnd(this);
|
||||
}
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
class INodeVisitor;
|
||||
|
||||
class Property
|
||||
{
|
||||
Q_DISABLE_COPY(Property)
|
||||
public:
|
||||
Property() = default;
|
||||
explicit Property(QByteArray name, QVariant value);
|
||||
virtual ~Property() = default;
|
||||
|
||||
QByteArray name() const { return m_name; }
|
||||
void setName(QByteArray name) { m_name = std::move(name); }
|
||||
|
||||
QVariant value() const { return m_value; }
|
||||
void setValue(QVariant value) { m_value = std::move(value); }
|
||||
|
||||
template<class T>
|
||||
T *appendChild(std::unique_ptr<T> child) {
|
||||
const auto p = child.get();
|
||||
m_children.push_back(std::move(child));
|
||||
return p;
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
T *appendChild(Args&&... args) {
|
||||
return appendChild(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
void appendProperty(QByteArray name, QVariant value = QVariant());
|
||||
void appendMultiLineProperty(QByteArray key, QStringList values,
|
||||
QChar sep = QLatin1Char(','));
|
||||
|
||||
virtual void accept(INodeVisitor *visitor) const;
|
||||
|
||||
protected:
|
||||
const std::vector<std::unique_ptr<Property>> &children() const
|
||||
{ return m_children; }
|
||||
|
||||
private:
|
||||
QByteArray m_name;
|
||||
QVariant m_value;
|
||||
std::vector<std::unique_ptr<Property>> m_children;
|
||||
};
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "xmlnodevisitor.h"
|
||||
#include "xmlpropertygroup.h"
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
PropertyGroup::PropertyGroup(QByteArray name)
|
||||
{
|
||||
setName(std::move(name));
|
||||
}
|
||||
|
||||
PropertyGroup *PropertyGroup::appendPropertyGroup(QByteArray name)
|
||||
{
|
||||
return appendChild<PropertyGroup>(std::move(name));
|
||||
}
|
||||
|
||||
void PropertyGroup::accept(INodeVisitor *visitor) const
|
||||
{
|
||||
visitor->visitPropertyGroupStart(this);
|
||||
|
||||
for (const auto &child : children())
|
||||
child->accept(visitor);
|
||||
|
||||
visitor->visitPropertyGroupEnd(this);
|
||||
}
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlproperty.h"
|
||||
|
||||
#include <projectexplorer/abi.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace BareMetal {
|
||||
|
||||
class ProductData;
|
||||
class Project;
|
||||
|
||||
namespace Gen {
|
||||
namespace Xml {
|
||||
|
||||
class PropertyGroup : public Property
|
||||
{
|
||||
public:
|
||||
explicit PropertyGroup(QByteArray name);
|
||||
PropertyGroup *appendPropertyGroup(QByteArray name);
|
||||
|
||||
void accept(INodeVisitor *visitor) const final;
|
||||
};
|
||||
|
||||
} // namespace Xml
|
||||
} // namespace Gen
|
||||
} // namespace BareMetal
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <QSpinBox>
|
||||
#include <QUuid>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace BareMetal {
|
||||
namespace Internal {
|
||||
|
||||
@@ -123,12 +126,12 @@ void IDebugServerProvider::setTypeDisplayName(const QString &typeDisplayName)
|
||||
m_typeDisplayName = typeDisplayName;
|
||||
}
|
||||
|
||||
Debugger::DebuggerEngineType IDebugServerProvider::engineType() const
|
||||
DebuggerEngineType IDebugServerProvider::engineType() const
|
||||
{
|
||||
return m_engineType;
|
||||
}
|
||||
|
||||
void IDebugServerProvider::setEngineType(Debugger::DebuggerEngineType engineType)
|
||||
void IDebugServerProvider::setEngineType(DebuggerEngineType engineType)
|
||||
{
|
||||
if (m_engineType == engineType)
|
||||
return;
|
||||
@@ -196,8 +199,8 @@ bool IDebugServerProvider::fromMap(const QVariantMap &data)
|
||||
{
|
||||
m_id = data.value(idKeyC).toString();
|
||||
m_displayName = data.value(displayNameKeyC).toString();
|
||||
m_engineType = static_cast<Debugger::DebuggerEngineType>(
|
||||
data.value(engineTypeKeyC, Debugger::NoEngineType).toInt());
|
||||
m_engineType = static_cast<DebuggerEngineType>(
|
||||
data.value(engineTypeKeyC, NoEngineType).toInt());
|
||||
m_channel.setHost(data.value(m_settingsBase + hostKeySuffixC).toString());
|
||||
m_channel.setPort(data.value(m_settingsBase + portKeySuffixC).toInt());
|
||||
return true;
|
||||
|
||||
@@ -25,15 +25,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
#include <debugger/debuggerconstants.h>
|
||||
#include <projectexplorer/abi.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QVariantMap>
|
||||
#include <QWidget>
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
#include <debugger/debuggerconstants.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QFormLayout;
|
||||
class QLabel;
|
||||
@@ -46,7 +47,6 @@ class DebuggerRunTool;
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class IDevice;
|
||||
class RunControl;
|
||||
class RunWorker;
|
||||
}
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
ProjectExplorer::RunControl *runControl) const = 0;
|
||||
|
||||
virtual bool isValid() const = 0;
|
||||
virtual bool isSimulator() const { return false; }
|
||||
|
||||
void registerDevice(BareMetalDevice *device);
|
||||
void unregisterDevice(BareMetalDevice *device);
|
||||
|
||||
@@ -89,6 +89,11 @@ add_qtc_plugin(Debugger
|
||||
threaddata.h
|
||||
threadshandler.cpp threadshandler.h
|
||||
unstartedappwatcherdialog.cpp unstartedappwatcherdialog.h
|
||||
uvsc/uvscclient.cpp uvsc/uvscclient.h
|
||||
uvsc/uvscdatatypes.h
|
||||
uvsc/uvscengine.cpp uvsc/uvscengine.h
|
||||
uvsc/uvscfunctions.h
|
||||
uvsc/uvscutils.cpp uvsc/uvscutils.h
|
||||
watchdata.cpp watchdata.h
|
||||
watchdelegatewidgets.cpp watchdelegatewidgets.h
|
||||
watchhandler.cpp watchhandler.h
|
||||
|
||||
@@ -133,6 +133,7 @@ include(cdb/cdb.pri)
|
||||
include(gdb/gdb.pri)
|
||||
include(pdb/pdb.pri)
|
||||
include(lldb/lldb.pri)
|
||||
include(uvsc/uvsc.pri)
|
||||
include(qml/qml.pri)
|
||||
include(namedemangler/namedemangler.pri)
|
||||
include(console/console.pri)
|
||||
|
||||
@@ -126,6 +126,18 @@ Project {
|
||||
files: ["pdbengine.cpp", "pdbengine.h"]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "uvsc"
|
||||
prefix: "uvsc/"
|
||||
files: [
|
||||
"uvscclient.cpp", "uvscclient.h",
|
||||
"uvscdatatypes.h",
|
||||
"uvscengine.cpp", "uvscengine.h",
|
||||
"uvscfunctions.h",
|
||||
"uvscutils.cpp", "uvscutils.h",
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Name Demangler"
|
||||
prefix: "namedemangler/"
|
||||
|
||||
@@ -36,6 +36,11 @@ const char MODE_DEBUG[] = "Mode.Debug";
|
||||
// Debug mode context
|
||||
const char C_DEBUGMODE[] = "Debugger.DebugMode";
|
||||
|
||||
// UVSC-specific debugger constants.
|
||||
const char kUVisionProjectFilePath[] = "UVisionProjectFilePath";
|
||||
const char kUVisionOptionsFilePath[] = "UVisionOptionsFilePath";
|
||||
const char kUVisionSimulator[] = "UVisionSimulator";
|
||||
|
||||
} // namespace Constants
|
||||
|
||||
// Keep in sync with dumper.py
|
||||
@@ -120,7 +125,8 @@ enum DebuggerEngineType
|
||||
GdbEngineType = 0x001,
|
||||
CdbEngineType = 0x004,
|
||||
PdbEngineType = 0x008,
|
||||
LldbEngineType = 0x100
|
||||
LldbEngineType = 0x100,
|
||||
UvscEngineType = 0x1000
|
||||
};
|
||||
|
||||
enum DebuggerLanguage
|
||||
|
||||
@@ -2567,7 +2567,8 @@ bool DebuggerRunParameters::isCppDebugging() const
|
||||
{
|
||||
return cppEngineType == GdbEngineType
|
||||
|| cppEngineType == LldbEngineType
|
||||
|| cppEngineType == CdbEngineType;
|
||||
|| cppEngineType == CdbEngineType
|
||||
|| cppEngineType == UvscEngineType;
|
||||
}
|
||||
|
||||
bool DebuggerRunParameters::isNativeMixedDebugging() const
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <utils/utilsicons.h>
|
||||
#include <utils/winutils.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
@@ -138,6 +139,14 @@ void DebuggerItem::createId()
|
||||
m_id = QUuid::createUuid().toString();
|
||||
}
|
||||
|
||||
static bool isUVisionExecutable(const QFileInfo &fileInfo)
|
||||
{
|
||||
if (!HostOsInfo::isWindowsHost())
|
||||
return false;
|
||||
const QString baseName = fileInfo.baseName();
|
||||
return baseName == "UV4";
|
||||
}
|
||||
|
||||
void DebuggerItem::reinitializeFromFile()
|
||||
{
|
||||
// CDB only understands the single-dash -version, whereas GDB and LLDB are
|
||||
@@ -149,6 +158,18 @@ void DebuggerItem::reinitializeFromFile()
|
||||
if (fileInfo.baseName().toLower().contains("lldb-mi"))
|
||||
version = "--version";
|
||||
|
||||
// We don't need to start the uVision executable to
|
||||
// determine its version.
|
||||
if (isUVisionExecutable(fileInfo)) {
|
||||
QString errorMessage;
|
||||
m_version = winGetDLLVersion(WinDLLFileVersion,
|
||||
fileInfo.absoluteFilePath(),
|
||||
&errorMessage);
|
||||
m_engineType = UvscEngineType;
|
||||
m_abis.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
SynchronousProcess proc;
|
||||
SynchronousProcessResponse response = proc.runBlocking({m_command, {version}});
|
||||
if (response.result != SynchronousProcessResponse::Finished) {
|
||||
@@ -236,6 +257,8 @@ QString DebuggerItem::engineTypeName() const
|
||||
return QLatin1String("CDB");
|
||||
case LldbEngineType:
|
||||
return QLatin1String("LLDB");
|
||||
case UvscEngineType:
|
||||
return QLatin1String("UVSC");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
void readDebuggers(const FilePath &fileName, bool isSystem);
|
||||
void autoDetectCdbDebuggers();
|
||||
void autoDetectGdbOrLldbDebuggers();
|
||||
void autoDetectUvscDebuggers();
|
||||
QString uniqueDisplayName(const QString &base);
|
||||
|
||||
PersistentSettingsWriter m_writer;
|
||||
@@ -788,6 +789,47 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers()
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerItemManagerPrivate::autoDetectUvscDebuggers()
|
||||
{
|
||||
if (!HostOsInfo::isWindowsHost())
|
||||
return;
|
||||
|
||||
// Registry token for the "KEIL uVision" instance.
|
||||
static const char kRegistryToken[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \
|
||||
"Windows\\CurrentVersion\\Uninstall\\Keil \u00B5Vision4";
|
||||
|
||||
QSettings registry(QLatin1String(kRegistryToken), QSettings::NativeFormat);
|
||||
const auto productGroups = registry.childGroups();
|
||||
for (const QString &productKey : productGroups) {
|
||||
if (!productKey.startsWith("App"))
|
||||
continue;
|
||||
registry.beginGroup(productKey);
|
||||
const QDir rootPath(registry.value("Directory").toString());
|
||||
registry.endGroup();
|
||||
const FilePath uVision = FilePath::fromString(
|
||||
rootPath.absoluteFilePath("UV4/UV4.exe"));
|
||||
if (!uVision.exists())
|
||||
continue;
|
||||
if (DebuggerItemManager::findByCommand(uVision))
|
||||
continue;
|
||||
|
||||
QString errorMsg;
|
||||
const QString uVisionVersion = winGetDLLVersion(
|
||||
WinDLLFileVersion, uVision.toString(), &errorMsg);
|
||||
|
||||
DebuggerItem item;
|
||||
item.createId();
|
||||
item.setAutoDetected(true);
|
||||
item.setCommand(uVision);
|
||||
item.setVersion(uVisionVersion);
|
||||
item.setEngineType(UvscEngineType);
|
||||
item.setUnexpandedDisplayName(
|
||||
uniqueDisplayName(tr("Auto-detected uVision at %1")
|
||||
.arg(uVision.toUserOutput())));
|
||||
m_model->addDebugger(item);
|
||||
}
|
||||
}
|
||||
|
||||
static FilePath userSettingsFileName()
|
||||
{
|
||||
return FilePath::fromString(ICore::userResourcePath() + DEBUGGER_FILENAME);
|
||||
@@ -894,6 +936,7 @@ void DebuggerItemManagerPrivate::restoreDebuggers()
|
||||
// Auto detect current.
|
||||
autoDetectCdbDebuggers();
|
||||
autoDetectGdbOrLldbDebuggers();
|
||||
autoDetectUvscDebuggers();
|
||||
}
|
||||
|
||||
void DebuggerItemManagerPrivate::saveDebuggers()
|
||||
|
||||
@@ -93,6 +93,7 @@ DebuggerEngine *createGdbEngine();
|
||||
DebuggerEngine *createPdbEngine();
|
||||
DebuggerEngine *createQmlEngine();
|
||||
DebuggerEngine *createLldbEngine();
|
||||
DebuggerEngine *createUvscEngine();
|
||||
|
||||
class LocalProcessRunner : public RunWorker
|
||||
{
|
||||
@@ -598,6 +599,9 @@ void DebuggerRunTool::start()
|
||||
QTC_CHECK(false); // Called from DebuggerRunTool constructor already.
|
||||
// m_engine = createPdbEngine();
|
||||
break;
|
||||
case UvscEngineType:
|
||||
m_engine = createUvscEngine();
|
||||
break;
|
||||
default:
|
||||
if (!m_runParameters.isQmlDebugging) {
|
||||
reportFailure(DebuggerPlugin::tr("Unable to create a debugging engine. "
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
HEADERS += \
|
||||
$$PWD/uvscclient.h \
|
||||
$$PWD/uvscdatatypes.h \
|
||||
$$PWD/uvscengine.h \
|
||||
$$PWD/uvscfunctions.h \
|
||||
$$PWD/uvscutils.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/uvscclient.cpp \
|
||||
$$PWD/uvscengine.cpp \
|
||||
$$PWD/uvscutils.cpp
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <debugger/debuggerprotocol.h>
|
||||
#include <debugger/registerhandler.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDir;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// From UVSC api.
|
||||
struct STACKENUM;
|
||||
|
||||
namespace Utils { class FilePath; }
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// UvscClient
|
||||
|
||||
class UvscClient final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using Registers = std::map<int, Register>;
|
||||
|
||||
enum UvscError {
|
||||
NoError,
|
||||
InitializationError,
|
||||
ConnectionError,
|
||||
ConfigurationError,
|
||||
RuntimeError,
|
||||
};
|
||||
|
||||
explicit UvscClient(const QDir &uvscDir);
|
||||
~UvscClient() final;
|
||||
|
||||
void version(QString &uvscVersion, QString &uvsockVersion);
|
||||
|
||||
bool connectSession(qint32 uvscPort);
|
||||
void disconnectSession();
|
||||
bool startSession(bool extendedStack);
|
||||
bool stopSession();
|
||||
|
||||
bool executeStepOver();
|
||||
bool executeStepIn();
|
||||
bool executeStepOut();
|
||||
bool executeStepInstruction();
|
||||
|
||||
bool startExecution();
|
||||
bool stopExecution();
|
||||
|
||||
bool fetchThreads(bool showNames, GdbMi &data);
|
||||
bool fetchStackFrames(quint32 taskId, quint64 address, GdbMi &data);
|
||||
bool fetchRegisters(Registers ®isters);
|
||||
|
||||
bool fetchLocals(const QStringList &expandedLocalINames, qint32 taskId,
|
||||
qint32 frameId, GdbMi &data);
|
||||
|
||||
bool fetchWatchers(const QStringList &expandedWatcherINames,
|
||||
const std::vector<std::pair<QString, QString>> &rootWatchers, GdbMi &data);
|
||||
|
||||
bool disassemblyAddress(quint64 address, QByteArray &result);
|
||||
|
||||
bool setRegisterValue(int index, const QString &value);
|
||||
bool setLocalValue(qint32 localId, qint32 taskId, qint32 frameId, const QString &value);
|
||||
bool setWatcherValue(qint32 watcherId, const QString &value);
|
||||
|
||||
bool createBreakpoint(const QString &exp, quint32 &tickMark, quint64 &address,
|
||||
quint32 &line, QString &function, QString &fileName);
|
||||
bool deleteBreakpoint(quint32 tickMark);
|
||||
bool enableBreakpoint(quint32 tickMark);
|
||||
bool disableBreakpoint(quint32 tickMark);
|
||||
|
||||
bool calculateExpression(const QString &exp, QByteArray &);
|
||||
|
||||
bool openProject(const Utils::FilePath &projectFile);
|
||||
void closeProject();
|
||||
bool setProjectSources(const Utils::FilePath &sourceDirectory,
|
||||
const Utils::FilePaths &sourceFiles);
|
||||
bool setProjectDebugTarget(bool simulator);
|
||||
bool setProjectOutputTarget(const Utils::FilePath &outputFile);
|
||||
|
||||
// Helper functions (for testing purposes only).
|
||||
void showWindow();
|
||||
void hideWindow();
|
||||
|
||||
UvscError error() const;
|
||||
QString errorString() const;
|
||||
|
||||
signals:
|
||||
void errorOccurred(UvscError error);
|
||||
void executionStarted();
|
||||
void executionStopped();
|
||||
void projectClosed();
|
||||
void locationUpdated(quint64 address);
|
||||
|
||||
private:
|
||||
void customEvent(QEvent *event) final;
|
||||
|
||||
bool checkConnection();
|
||||
bool enumerateStack(quint32 taskId, std::vector<STACKENUM> &stackenums);
|
||||
bool inspectLocal(const QStringList &expandedLocalINames, const QString &localIName,
|
||||
qint32 localId, qint32 taskId, qint32 frameId, GdbMi &data);
|
||||
bool fetchWatcher(const QStringList &expandedWatcherINames,
|
||||
const std::pair<QString, QString> &rootWatcher, GdbMi &data);
|
||||
bool inspectWatcher(const QStringList &expandedWatcherINames, qint32 watcherId,
|
||||
const QString &watcherIName, GdbMi &parent);
|
||||
void setError(UvscError error, const QString &errorString = QString());
|
||||
void handleMsgEvent(QEvent *event);
|
||||
void updateLocation(const QByteArray &bpreason);
|
||||
bool addressToFileLine(quint64 address, QString &fileName, QString &function, quint32 &line);
|
||||
|
||||
qint32 m_descriptor = -1;
|
||||
quint64 m_exitAddress = 0;
|
||||
UvscError m_error = NoError;
|
||||
QString m_errorString;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,828 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvscengine.h"
|
||||
#include "uvscutils.h"
|
||||
|
||||
#include <debugger/breakhandler.h>
|
||||
#include <debugger/debuggercore.h>
|
||||
#include <debugger/disassembleragent.h>
|
||||
#include <debugger/disassemblerlines.h>
|
||||
#include <debugger/memoryagent.h>
|
||||
#include <debugger/moduleshandler.h>
|
||||
#include <debugger/registerhandler.h>
|
||||
#include <debugger/stackhandler.h>
|
||||
#include <debugger/threadshandler.h>
|
||||
#include <debugger/watchhandler.h>
|
||||
|
||||
#include <coreplugin/messagebox.h>
|
||||
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
constexpr int kRootStackFrameLevel = 1;
|
||||
|
||||
// This is a workaround to enable the enumeration of a locals
|
||||
// in a main/root stack. We need to remove a file in a form
|
||||
// of 'projectname.uvguix.username' which are creates by uVision.
|
||||
// Yes, it is a magic!
|
||||
static void allowRootLocals(const FilePath &projectFile)
|
||||
{
|
||||
const QFileInfo fi(projectFile.toFileInfo());
|
||||
if (!fi.exists())
|
||||
return;
|
||||
const QString baseName = fi.baseName();
|
||||
const QDir dir(fi.dir());
|
||||
const QString filter = QStringLiteral("%1.uvguix.*").arg(baseName);
|
||||
const QFileInfoList trashFileInfos = dir.entryInfoList({filter}, QDir::Files);
|
||||
for (const QFileInfo &trashFileInfo : trashFileInfos) {
|
||||
QFile f(trashFileInfo.absoluteFilePath());
|
||||
f.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Accessed by DebuggerRunTool.
|
||||
DebuggerEngine *createUvscEngine()
|
||||
{
|
||||
return new UvscEngine;
|
||||
}
|
||||
|
||||
// UvscEngine
|
||||
|
||||
UvscEngine::UvscEngine()
|
||||
{
|
||||
setObjectName("UvscEngine");
|
||||
setDebuggerName("UVSC");
|
||||
}
|
||||
|
||||
void UvscEngine::setupEngine()
|
||||
{
|
||||
showMessage("TRYING TO INITIALIZE UVSC");
|
||||
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
|
||||
// Extract the TCP/IP port for running uVision server.
|
||||
const QUrl channel(rp.remoteChannel);
|
||||
const int port = channel.port();
|
||||
if (port <= 0) {
|
||||
handleSetupFailure(tr("Internal error: Invalid TCP/IP port specified %1.")
|
||||
.arg(port));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for valid uVision executable.
|
||||
if (rp.debugger.executable.isEmpty()) {
|
||||
handleSetupFailure(tr("Internal error: There is no uVision executable specified."));
|
||||
return;
|
||||
} else if (!rp.debugger.executable.exists()) {
|
||||
handleSetupFailure(tr("Internal error: There is no uVision executable exists."));
|
||||
return;
|
||||
}
|
||||
|
||||
showMessage("UVSC: RESOLVING LIBRARY SYMBOLS...");
|
||||
m_client.reset(new UvscClient(rp.debugger.executable.parentDir().toString()));
|
||||
if (m_client->error() != UvscClient::NoError) {
|
||||
handleSetupFailure(tr("Internal error: Cannot resolve the library: %1.")
|
||||
.arg(m_client->errorString()));
|
||||
return;
|
||||
} else {
|
||||
// Show the client API version.
|
||||
QString uvscVersion;
|
||||
QString uvsockVersion;
|
||||
m_client->version(uvscVersion, uvsockVersion);
|
||||
const QString msg = tr("UVSC Version: %1, UVSOCK Version: %2.")
|
||||
.arg(uvscVersion, uvsockVersion);
|
||||
showMessage(msg, LogMisc);
|
||||
|
||||
// Conenct to the client signals.
|
||||
connect(m_client.get(), &UvscClient::errorOccurred,
|
||||
this, [this](UvscClient::UvscError error) {
|
||||
// Handle errors if required.
|
||||
Q_UNUSED(error)
|
||||
Q_UNUSED(this)
|
||||
});
|
||||
connect(m_client.get(), &UvscClient::executionStarted,
|
||||
this, &UvscEngine::handleStartExecution);
|
||||
connect(m_client.get(), &UvscClient::executionStopped,
|
||||
this, &UvscEngine::handleStopExecution);
|
||||
connect(m_client.get(), &UvscClient::projectClosed,
|
||||
this, &UvscEngine::handleProjectClosed);
|
||||
connect(m_client.get(), &UvscClient::locationUpdated,
|
||||
this, &UvscEngine::handleUpdateLocation);
|
||||
}
|
||||
|
||||
showMessage("UVSC: CONNECTING SESSION...");
|
||||
if (!m_client->connectSession(port)) {
|
||||
handleSetupFailure(tr("Internal error: Cannot open the session: %1.")
|
||||
.arg(m_client->errorString()));
|
||||
return;
|
||||
} else {
|
||||
showMessage("UVSC: SESSION OPENED.");
|
||||
// Show window (fot testing only).
|
||||
//m_client->showWindow();
|
||||
}
|
||||
|
||||
if (!configureProject(rp))
|
||||
return;
|
||||
}
|
||||
|
||||
void UvscEngine::runEngine()
|
||||
{
|
||||
showMessage("UVSC: STARTING DEBUGGER...");
|
||||
if (!m_client->startSession(true)) {
|
||||
showStatusMessage(tr("Internal error: Failed to start the debugger: %1")
|
||||
.arg(m_client->errorString()));
|
||||
notifyEngineRunFailed();
|
||||
return;
|
||||
} else {
|
||||
showMessage("UVSC: DEBUGGER STARTED");
|
||||
showMessage(tr("Application started."), StatusBar);
|
||||
}
|
||||
|
||||
// Initial attempt to set breakpoints.
|
||||
showStatusMessage(tr("Setting breakpoints..."));
|
||||
showMessage(tr("Setting breakpoints..."));
|
||||
BreakpointManager::claimBreakpointsForEngine(this);
|
||||
|
||||
showMessage("UVSC RUNNING SUCCESSFULLY.");
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
}
|
||||
|
||||
void UvscEngine::shutdownInferior()
|
||||
{
|
||||
showMessage("UVSC: STOPPING DEBUGGER...");
|
||||
if (!m_client->stopSession()) {
|
||||
AsynchronousMessageBox::critical(tr("Failed to Shut Down Application"),
|
||||
m_client->errorString());
|
||||
} else {
|
||||
showMessage("UVSC: DEBUGGER STOPPED");
|
||||
}
|
||||
|
||||
notifyInferiorShutdownFinished();
|
||||
}
|
||||
|
||||
void UvscEngine::shutdownEngine()
|
||||
{
|
||||
showMessage("INITIATE UVSC SHUTDOWN");
|
||||
m_client->disconnectSession();
|
||||
notifyEngineShutdownFinished();
|
||||
}
|
||||
|
||||
bool UvscEngine::hasCapability(unsigned cap) const
|
||||
{
|
||||
return cap & (DisassemblerCapability
|
||||
| RegisterCapability
|
||||
| AddWatcherCapability
|
||||
| WatchWidgetsCapability
|
||||
| CreateFullBacktraceCapability
|
||||
| OperateByInstructionCapability);
|
||||
}
|
||||
|
||||
void UvscEngine::setRegisterValue(const QString &name, const QString &value)
|
||||
{
|
||||
const auto registerBegin = m_registers.cbegin();
|
||||
const auto registerEnd = m_registers.cend();
|
||||
const auto registerIt = std::find_if(registerBegin, registerEnd,
|
||||
[name](const std::pair<int, Register> ®) {
|
||||
return reg.second.name == name;
|
||||
});
|
||||
if (registerIt == registerEnd)
|
||||
return; // Register not found.
|
||||
if (!m_client->setRegisterValue(registerIt->first, value))
|
||||
return;
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
void UvscEngine::executeStepOver(bool byInstruction)
|
||||
{
|
||||
notifyInferiorRunRequested();
|
||||
const quint32 frameLevel = currentFrameLevel();
|
||||
// UVSC does not support the 'step-over' from the main
|
||||
// stack frame (seems, it is UVSC bug), so, falling back
|
||||
// to the 'step-by-instruction' in this case.
|
||||
const bool result = (frameLevel == kRootStackFrameLevel || byInstruction)
|
||||
? m_client->executeStepInstruction() : m_client->executeStepOver();
|
||||
if (!result)
|
||||
handleExecutionFailure(m_client->errorString());
|
||||
}
|
||||
|
||||
void UvscEngine::executeStepIn(bool byInstruction)
|
||||
{
|
||||
notifyInferiorRunRequested();
|
||||
const quint32 frameLevel = currentFrameLevel();
|
||||
// UVSC does not support the 'step-over' from the main
|
||||
// stack frame (seems, it is UVSC bug), so, falling back
|
||||
// to the 'step-by-instruction' in this case.
|
||||
const bool result = (frameLevel == kRootStackFrameLevel || byInstruction)
|
||||
? m_client->executeStepInstruction() : m_client->executeStepIn();
|
||||
if (!result)
|
||||
handleExecutionFailure(m_client->errorString());
|
||||
}
|
||||
|
||||
void UvscEngine::executeStepOut()
|
||||
{
|
||||
notifyInferiorRunRequested();
|
||||
if (!m_client->executeStepOut())
|
||||
handleExecutionFailure(m_client->errorString());
|
||||
}
|
||||
|
||||
void UvscEngine::continueInferior()
|
||||
{
|
||||
if (state() != InferiorStopOk)
|
||||
return;
|
||||
|
||||
notifyInferiorRunRequested();
|
||||
showStatusMessage(tr("Running requested..."), 5000);
|
||||
|
||||
if (!m_client->startExecution()) {
|
||||
showMessage(tr("UVSC: Starting execution failed"), LogMisc);
|
||||
handleExecutionFailure(m_client->errorString());
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::interruptInferior()
|
||||
{
|
||||
if (state() != InferiorStopRequested)
|
||||
return;
|
||||
|
||||
if (!m_client->stopExecution()) {
|
||||
showMessage(tr("UVSC: Stopping execution failed"), LogMisc);
|
||||
handleStoppingFailure(m_client->errorString());
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::assignValueInDebugger(WatchItem *item, const QString &expr,
|
||||
const QVariant &value)
|
||||
{
|
||||
Q_UNUSED(expr)
|
||||
|
||||
if (item->isLocal()) {
|
||||
const int taskId = currentThreadId();
|
||||
const int frameId = currentFrameLevel();
|
||||
if (!m_client->setLocalValue(item->id, taskId, frameId, value.toString()))
|
||||
showMessage(tr("UVSC: Setting local value failed"), LogMisc);
|
||||
} else if (item->isWatcher()) {
|
||||
if (!m_client->setWatcherValue(item->id, value.toString()))
|
||||
showMessage(tr("UVSC: Setting watcher value failed"), LogMisc);
|
||||
}
|
||||
|
||||
updateLocals();
|
||||
}
|
||||
|
||||
void UvscEngine::selectThread(const Thread &thread)
|
||||
{
|
||||
Q_UNUSED(thread)
|
||||
|
||||
// We don't support this feature, because we always have
|
||||
// only one main thread.
|
||||
}
|
||||
|
||||
void UvscEngine::activateFrame(int index)
|
||||
{
|
||||
if (state() != InferiorStopOk && state() != InferiorUnrunnable)
|
||||
return;
|
||||
|
||||
StackHandler *handler = stackHandler();
|
||||
if (handler->isSpecialFrame(index)) {
|
||||
reloadFullStack();
|
||||
return;
|
||||
}
|
||||
|
||||
QTC_ASSERT(index < handler->stackSize(), return);
|
||||
handler->setCurrentIndex(index);
|
||||
|
||||
gotoCurrentLocation();
|
||||
updateLocals();
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
bool UvscEngine::stateAcceptsBreakpointChanges() const
|
||||
{
|
||||
switch (state()) {
|
||||
case InferiorRunOk:
|
||||
case InferiorStopOk:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UvscEngine::acceptsBreakpoint(const BreakpointParameters &bp) const
|
||||
{
|
||||
if (bp.isCppBreakpoint()) {
|
||||
switch (bp.type) {
|
||||
case BreakpointByFileAndLine:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UvscEngine::insertBreakpoint(const Breakpoint &bp)
|
||||
{
|
||||
if (!bp || bp->state() != BreakpointInsertionRequested)
|
||||
return;
|
||||
|
||||
notifyBreakpointInsertProceeding(bp);
|
||||
|
||||
const BreakpointParameters &requested = bp->requestedParameters();
|
||||
QString expression;
|
||||
if (requested.type == BreakpointByFileAndLine) {
|
||||
// Add target executable name.
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
QString exe = rp.inferior.executable.toFileInfo().baseName();
|
||||
exe.replace('-', '_');
|
||||
expression += "\\\\" + exe;
|
||||
// Add file name.
|
||||
expression += "\\" + requested.fileName.toString();
|
||||
// Add line number.
|
||||
expression += "\\" + QString::number(requested.lineNumber);
|
||||
}
|
||||
|
||||
handleInsertBreakpoint(expression, bp);
|
||||
}
|
||||
|
||||
void UvscEngine::removeBreakpoint(const Breakpoint &bp)
|
||||
{
|
||||
if (!bp || bp->state() != BreakpointRemoveRequested || bp->responseId().isEmpty())
|
||||
return;
|
||||
|
||||
notifyBreakpointRemoveProceeding(bp);
|
||||
handleRemoveBreakpoint(bp);
|
||||
}
|
||||
|
||||
void UvscEngine::updateBreakpoint(const Breakpoint &bp)
|
||||
{
|
||||
if (!bp || bp->state() != BreakpointUpdateRequested || bp->responseId().isEmpty())
|
||||
return;
|
||||
|
||||
const BreakpointParameters &requested = bp->requestedParameters();
|
||||
if (requested.type == UnknownBreakpointType)
|
||||
return;
|
||||
|
||||
notifyBreakpointChangeProceeding(bp);
|
||||
handleChangeBreakpoint(bp);
|
||||
}
|
||||
|
||||
void UvscEngine::fetchDisassembler(DisassemblerAgent *agent)
|
||||
{
|
||||
QByteArray data;
|
||||
const Location location = agent->location();
|
||||
if (const quint64 address = location.address()) {
|
||||
if (!m_client->disassemblyAddress(address, data))
|
||||
showMessage(tr("UVSC: Disassembling by address failed"), LogMisc);
|
||||
}
|
||||
|
||||
DisassemblerLines result;
|
||||
QTextStream in(data);
|
||||
while (!in.atEnd()) {
|
||||
const QString line = in.readLine();
|
||||
if (line.startsWith("0x")) {
|
||||
// Instruction line, like:
|
||||
// "0x08000210 9101 STR r1,[sp,#0x04]".
|
||||
const int oneSpaceIndex = line.indexOf(' ');
|
||||
if (oneSpaceIndex < 0)
|
||||
continue;
|
||||
const QString address = line.mid(0, oneSpaceIndex);
|
||||
const int sixSpaceIndex = line.indexOf(" ", oneSpaceIndex);
|
||||
if (sixSpaceIndex < 0)
|
||||
continue;
|
||||
const QString bytes = line.mid(oneSpaceIndex + 1, sixSpaceIndex - oneSpaceIndex - 1);
|
||||
const QString content = line.mid(sixSpaceIndex + 6);
|
||||
DisassemblerLine dline;
|
||||
dline.address = address.toULongLong(nullptr, 0);
|
||||
dline.bytes = bytes;
|
||||
dline.data = content;
|
||||
result.appendLine(dline);
|
||||
} else {
|
||||
// Comment or code line, like:
|
||||
// " 25: struct foo foo = {0}; ".
|
||||
const int colonIndex = line.indexOf(':');
|
||||
if (colonIndex < 0) {
|
||||
result.appendComment(line);
|
||||
} else {
|
||||
const QString number = line.mid(0, colonIndex).trimmed();
|
||||
const QString content = line.mid(colonIndex + 1);
|
||||
DisassemblerLine dline;
|
||||
dline.lineNumber = number.toInt();
|
||||
dline.data = content;
|
||||
result.appendLine(dline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.coversAddress(agent->address())) {
|
||||
// We need to force cleanup a cache to make a location
|
||||
// marker work correctly in disassembly view.
|
||||
agent->cleanup();
|
||||
agent->setContents(result);
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::reloadRegisters()
|
||||
{
|
||||
if (!isRegistersWindowVisible())
|
||||
return;
|
||||
if (state() != InferiorStopOk && state() != InferiorUnrunnable)
|
||||
return;
|
||||
handleReloadRegisters();
|
||||
}
|
||||
|
||||
void UvscEngine::reloadFullStack()
|
||||
{
|
||||
resetLocation();
|
||||
handleReloadStack(true);
|
||||
}
|
||||
|
||||
void UvscEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
{
|
||||
if (m_inUpdateLocals)
|
||||
return;
|
||||
m_inUpdateLocals = true;
|
||||
|
||||
watchHandler()->notifyUpdateStarted(params);
|
||||
|
||||
const bool partial = !params.partialVariable.isEmpty();
|
||||
// This is a workaround to avoid a strange QVector index assertion
|
||||
// inside of the watch model.
|
||||
QMetaObject::invokeMethod(this, "handleUpdateLocals", Qt::QueuedConnection,
|
||||
Q_ARG(bool, partial));
|
||||
}
|
||||
|
||||
void UvscEngine::updateAll()
|
||||
{
|
||||
QTC_CHECK(state() == InferiorUnrunnable || state() == InferiorStopOk);
|
||||
|
||||
handleThreadInfo();
|
||||
reloadRegisters();
|
||||
updateLocals();
|
||||
}
|
||||
|
||||
bool UvscEngine::configureProject(const DebuggerRunParameters &rp)
|
||||
{
|
||||
// Fetch patchs for the generated uVision project files.
|
||||
const FilePath optionsPath = FilePath::fromString(rp.inferior.extraData.value(
|
||||
Constants::kUVisionOptionsFilePath).toString());
|
||||
const FilePath projectPath = FilePath::fromString(rp.inferior.extraData.value(
|
||||
Constants::kUVisionProjectFilePath).toString());
|
||||
|
||||
showMessage("UVSC: LOADING PROJECT...");
|
||||
if (!optionsPath.exists()) {
|
||||
handleSetupFailure(tr("Internal error: No uVision project options file exists."));
|
||||
return false;
|
||||
} else if (!projectPath.exists()) {
|
||||
handleSetupFailure(tr("Internal error: No uVision project file exists."));
|
||||
return false;
|
||||
} else if (!m_client->openProject(projectPath)) {
|
||||
handleSetupFailure(tr("Internal error: Unable to open the uVision project %1: %2.")
|
||||
.arg(projectPath.toString(), m_client->errorString()));
|
||||
return false;
|
||||
} else {
|
||||
showMessage("UVSC: PROJECT LOADED");
|
||||
}
|
||||
|
||||
showMessage("UVSC: SETTING PROJECT DEBUG TARGET...");
|
||||
m_simulator = rp.inferior.extraData.value(Constants::kUVisionSimulator).toBool();
|
||||
if (!m_client->setProjectDebugTarget(m_simulator)) {
|
||||
handleSetupFailure(tr("Internal error: Unable to set the uVision debug target: %1.")
|
||||
.arg(m_client->errorString()));
|
||||
return false;
|
||||
} else {
|
||||
showMessage("UVSC: PROJECT DEBUG TARGET SET");
|
||||
}
|
||||
|
||||
// We need to use the relative output target path.
|
||||
showMessage("UVSC: SETTING PROJECT OUTPUT TARGET...");
|
||||
const FilePath targetPath = rp.inferior.executable.relativeChildPath(
|
||||
projectPath.parentDir());
|
||||
if (!rp.inferior.executable.exists()) {
|
||||
handleSetupFailure(tr("Internal error: No output file exists."));
|
||||
return false;
|
||||
} else if (!m_client->setProjectOutputTarget(targetPath)) {
|
||||
handleSetupFailure(tr("Internal error: Unable to set the uVision output file %1: %2.")
|
||||
.arg(targetPath.toString(), m_client->errorString()));
|
||||
return false;
|
||||
} else {
|
||||
showMessage("UVSC: PROJECT OUTPUT TARGET SET");
|
||||
}
|
||||
|
||||
// Close the project to flush all changes to the
|
||||
// specific uVision project files.
|
||||
m_loadingRequired = true;
|
||||
m_client->closeProject();
|
||||
return true;
|
||||
}
|
||||
|
||||
quint32 UvscEngine::currentThreadId() const
|
||||
{
|
||||
const Thread thread = threadsHandler()->currentThread();
|
||||
return thread ? thread->id().toUInt() : -1;
|
||||
}
|
||||
|
||||
quint32 UvscEngine::currentFrameLevel() const
|
||||
{
|
||||
const StackFrame frame = stackHandler()->currentFrame();
|
||||
return frame.level.toUInt();
|
||||
}
|
||||
|
||||
void UvscEngine::handleProjectClosed()
|
||||
{
|
||||
if (!m_loadingRequired)
|
||||
return;
|
||||
m_loadingRequired = false;
|
||||
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
const FilePath projectPath = FilePath::fromString(rp.inferior.extraData.value(
|
||||
Constants::kUVisionProjectFilePath).toString());
|
||||
|
||||
// This magic function removes specific files from the uVision
|
||||
// project directory. Without of this we can't enumerate the local
|
||||
// variables on a root/main stack (yes, it is a magic)!
|
||||
allowRootLocals(projectPath);
|
||||
|
||||
// Re-open the project again.
|
||||
if (!m_client->openProject(projectPath)) {
|
||||
handleSetupFailure(tr("Internal error: Unable to open the uVision project %1: %2.")
|
||||
.arg(projectPath.toString(), m_client->errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Adding executable to modules list.
|
||||
Module module;
|
||||
module.startAddress = 0;
|
||||
module.endAddress = 0;
|
||||
module.modulePath = rp.inferior.executable.toString();
|
||||
module.moduleName = "<executable>";
|
||||
modulesHandler()->updateModule(module);
|
||||
|
||||
showMessage("UVSC: ALL INITIALIZED SUCCESSFULLY.");
|
||||
|
||||
notifyEngineSetupOk();
|
||||
}
|
||||
|
||||
void UvscEngine::handleUpdateLocation(quint64 address)
|
||||
{
|
||||
m_address = address;
|
||||
}
|
||||
|
||||
void UvscEngine::handleStartExecution()
|
||||
{
|
||||
notifyInferiorRunOk();
|
||||
}
|
||||
|
||||
void UvscEngine::handleStopExecution()
|
||||
{
|
||||
if (state() == InferiorRunOk) {
|
||||
notifyInferiorSpontaneousStop();
|
||||
} else if (state() == InferiorRunRequested) {
|
||||
notifyInferiorRunOk();
|
||||
notifyInferiorSpontaneousStop();
|
||||
} else if (state() == InferiorStopOk) {
|
||||
// That's expected.
|
||||
} else if (state() == InferiorStopRequested) {
|
||||
notifyInferiorStopOk();
|
||||
} else if (state() == EngineRunRequested) {
|
||||
// This is gdb 7+'s initial *stopped in response to attach that
|
||||
// appears before the ^done is seen for local setups.
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
} else {
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
|
||||
QTC_CHECK(state() == InferiorStopOk);
|
||||
handleThreadInfo();
|
||||
}
|
||||
|
||||
void UvscEngine::handleThreadInfo()
|
||||
{
|
||||
const bool showNames = true;
|
||||
GdbMi data;
|
||||
if (!m_client->fetchThreads(showNames, data))
|
||||
return;
|
||||
ThreadsHandler *handler = threadsHandler();
|
||||
handler->setThreads(data);
|
||||
updateState();
|
||||
handleReloadStack(false);
|
||||
}
|
||||
|
||||
void UvscEngine::handleReloadStack(bool isFull)
|
||||
{
|
||||
GdbMi data;
|
||||
const quint32 taskId = currentThreadId();
|
||||
if (!m_client->fetchStackFrames(taskId, m_address, data)) {
|
||||
m_address = 0;
|
||||
reloadRegisters();
|
||||
return;
|
||||
}
|
||||
|
||||
const GdbMi stack = data["stack"];
|
||||
const GdbMi frames = stack["frames"];
|
||||
if (!frames.isValid())
|
||||
isFull = true;
|
||||
|
||||
stackHandler()->setFramesAndCurrentIndex(frames, isFull);
|
||||
activateFrame(stackHandler()->currentIndex());
|
||||
}
|
||||
|
||||
void UvscEngine::handleReloadRegisters()
|
||||
{
|
||||
m_registers.clear();
|
||||
if (!m_client->fetchRegisters(m_registers)) {
|
||||
showMessage(tr("UVSC: Registers reading failed"), LogMisc);
|
||||
} else {
|
||||
RegisterHandler *handler = registerHandler();
|
||||
for (const auto ® : qAsConst(m_registers))
|
||||
handler->updateRegister(reg.second);
|
||||
handler->commitUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::handleUpdateLocals(bool partial)
|
||||
{
|
||||
m_inUpdateLocals = false;
|
||||
|
||||
// Build result entry.
|
||||
GdbMi all = UvscUtils::buildResultTemplateEntry(partial);
|
||||
// Build data entry.
|
||||
GdbMi data = UvscUtils::buildEntry("data", "", GdbMi::List);
|
||||
|
||||
const int taskId = currentThreadId();
|
||||
const int frameId = currentFrameLevel();
|
||||
|
||||
DebuggerCommand cmd;
|
||||
watchHandler()->appendFormatRequests(&cmd);
|
||||
watchHandler()->appendWatchersAndTooltipRequests(&cmd);
|
||||
|
||||
auto enumerateExpandedINames = [&cmd]() {
|
||||
QStringList inames;
|
||||
const QJsonArray array = cmd.args["expanded"].toArray();
|
||||
for (const QJsonValue &value : array)
|
||||
inames.push_back(value.toString());
|
||||
return inames;
|
||||
};
|
||||
|
||||
auto enumerateRootWatchers = [&cmd]() {
|
||||
std::vector<std::pair<QString, QString>> inames;
|
||||
const QJsonArray array = cmd.args["watchers"].toArray();
|
||||
for (const QJsonValue &value : array) {
|
||||
if (!value.isObject())
|
||||
continue;
|
||||
const QJsonObject object = value.toObject();
|
||||
inames.push_back({object.value("iname").toString(),
|
||||
object.value("exp").toString()});
|
||||
}
|
||||
return inames;
|
||||
};
|
||||
|
||||
const QStringList expandedINames = enumerateExpandedINames();
|
||||
const std::vector<std::pair<QString, QString>> rootWatchers = enumerateRootWatchers();
|
||||
QStringList expandedLocalINames;
|
||||
QStringList expandedWatcherINames;
|
||||
for (const QString &iname : expandedINames) {
|
||||
if (iname.startsWith("local."))
|
||||
expandedLocalINames.push_back(iname);
|
||||
else if (iname.startsWith("watch."))
|
||||
expandedWatcherINames.push_back(iname);
|
||||
}
|
||||
|
||||
if (!m_client->fetchLocals(expandedLocalINames, taskId, frameId, data))
|
||||
showMessage(tr("UVSC: Locals enumeration failed"), LogMisc);
|
||||
if (!m_client->fetchWatchers(expandedWatcherINames, rootWatchers, data))
|
||||
showMessage(tr("UVSC: Watchers enumeration failed"), LogMisc);
|
||||
|
||||
all.addChild(data);
|
||||
|
||||
updateLocalsView(all);
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
}
|
||||
|
||||
void UvscEngine::handleInsertBreakpoint(const QString &exp, const Breakpoint &bp)
|
||||
{
|
||||
quint32 tickMark = 0;
|
||||
quint64 address = 0;
|
||||
quint32 line = -1;
|
||||
QString function;
|
||||
QString fileName;
|
||||
if (!m_client->createBreakpoint(exp, tickMark, address, line, function, fileName)) {
|
||||
showMessage(tr("UVSC: Inserting breakpoint failed"), LogMisc);
|
||||
notifyBreakpointInsertFailed(bp);
|
||||
} else {
|
||||
bp->setPending(false);
|
||||
bp->setResponseId(QString::number(tickMark));
|
||||
bp->setAddress(address);
|
||||
bp->setLineNumber(line);
|
||||
bp->setFileName(FilePath::fromString(fileName));
|
||||
bp->setFunctionName(function);
|
||||
notifyBreakpointInsertOk(bp);
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::handleRemoveBreakpoint(const Breakpoint &bp)
|
||||
{
|
||||
const quint32 tickMark = bp->responseId().toULong();
|
||||
if (!m_client->deleteBreakpoint(tickMark)) {
|
||||
showMessage(tr("UVSC: Removing breakpoint failed"), LogMisc);
|
||||
notifyBreakpointRemoveFailed(bp);
|
||||
} else {
|
||||
notifyBreakpointRemoveOk(bp);
|
||||
}
|
||||
}
|
||||
|
||||
void UvscEngine::handleChangeBreakpoint(const Breakpoint &bp)
|
||||
{
|
||||
const quint32 tickMark = bp->responseId().toULong();
|
||||
const BreakpointParameters &requested = bp->requestedParameters();
|
||||
if (requested.enabled && !bp->isEnabled()) {
|
||||
if (!m_client->enableBreakpoint(tickMark)) {
|
||||
showMessage(tr("UVSC: Enabling breakpoint failed"), LogMisc);
|
||||
notifyBreakpointChangeFailed(bp);
|
||||
return;
|
||||
}
|
||||
} else if (!requested.enabled && bp->isEnabled()) {
|
||||
if (!m_client->disableBreakpoint(tickMark)) {
|
||||
showMessage(tr("UVSC: Disabling breakpoint failed"), LogMisc);
|
||||
notifyBreakpointChangeFailed(bp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
notifyBreakpointChangeOk(bp);
|
||||
}
|
||||
|
||||
void UvscEngine::handleSetupFailure(const QString &errorMessage)
|
||||
{
|
||||
showMessage("UVSC INITIALIZATION FAILED");
|
||||
AsynchronousMessageBox::critical(tr("Failed to initialize the UVSC"), errorMessage);
|
||||
notifyEngineSetupFailed();
|
||||
}
|
||||
|
||||
void UvscEngine::handleShutdownFailure(const QString &errorMessage)
|
||||
{
|
||||
showMessage("UVSC SHUTDOWN FAILED");
|
||||
AsynchronousMessageBox::critical(tr("Failed to de-initialize the UVSC"), errorMessage);
|
||||
}
|
||||
|
||||
void UvscEngine::handleRunFailure(const QString &errorMessage)
|
||||
{
|
||||
showMessage("UVSC RUN FAILED");
|
||||
AsynchronousMessageBox::critical(tr("Failed to run the UVSC"), errorMessage);
|
||||
notifyEngineSetupFailed();
|
||||
}
|
||||
|
||||
void UvscEngine::handleExecutionFailure(const QString &errorMessage)
|
||||
{
|
||||
AsynchronousMessageBox::critical(tr("Execution Error"),
|
||||
tr("Cannot continue debugged process:\n") + errorMessage);
|
||||
notifyInferiorRunFailed();
|
||||
}
|
||||
|
||||
void UvscEngine::handleStoppingFailure(const QString &errorMessage)
|
||||
{
|
||||
AsynchronousMessageBox::critical(tr("Execution Error"),
|
||||
tr("Cannot stop debugged process:\n") + errorMessage);
|
||||
notifyInferiorStopFailed();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvscclient.h"
|
||||
|
||||
#include <debugger/debuggerengine.h>
|
||||
|
||||
namespace Utils { class FilePath; }
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class UvscEngine final : public CppDebuggerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UvscEngine();
|
||||
|
||||
void setupEngine() final;
|
||||
void runEngine() final;
|
||||
void shutdownInferior() final;
|
||||
void shutdownEngine() final;
|
||||
|
||||
bool hasCapability(unsigned cap) const final;
|
||||
|
||||
void setRegisterValue(const QString &name, const QString &value) final;
|
||||
|
||||
void executeStepOver(bool byInstruction) final;
|
||||
void executeStepIn(bool byInstruction) final;
|
||||
void executeStepOut() final;
|
||||
|
||||
void continueInferior() final;
|
||||
void interruptInferior() final;
|
||||
|
||||
void assignValueInDebugger(WatchItem *item, const QString &expr, const QVariant &value) final;
|
||||
void selectThread(const Thread &thread) final;
|
||||
|
||||
void activateFrame(int index) final;
|
||||
|
||||
bool stateAcceptsBreakpointChanges() const final;
|
||||
bool acceptsBreakpoint(const BreakpointParameters ¶ms) const final;
|
||||
|
||||
void insertBreakpoint(const Breakpoint &bp) final;
|
||||
void removeBreakpoint(const Breakpoint &bp) final;
|
||||
void updateBreakpoint(const Breakpoint &bp) final;
|
||||
|
||||
void fetchDisassembler(DisassemblerAgent *agent) final;
|
||||
|
||||
void reloadRegisters() final;
|
||||
void reloadFullStack() final;
|
||||
|
||||
private slots:
|
||||
void handleProjectClosed();
|
||||
void handleUpdateLocation(quint64 address);
|
||||
|
||||
void handleStartExecution();
|
||||
void handleStopExecution();
|
||||
|
||||
void handleThreadInfo();
|
||||
void handleReloadStack(bool isFull);
|
||||
void handleReloadRegisters();
|
||||
void handleUpdateLocals(bool partial);
|
||||
void handleInsertBreakpoint(const QString &exp, const Breakpoint &bp);
|
||||
void handleRemoveBreakpoint(const Breakpoint &bp);
|
||||
void handleChangeBreakpoint(const Breakpoint &bp);
|
||||
|
||||
void handleSetupFailure(const QString &errorMessage);
|
||||
void handleShutdownFailure(const QString &errorMessage);
|
||||
void handleRunFailure(const QString &errorMessage);
|
||||
void handleExecutionFailure(const QString &errorMessage);
|
||||
void handleStoppingFailure(const QString &errorMessage);
|
||||
|
||||
private:
|
||||
void doUpdateLocals(const UpdateParameters ¶ms) final;
|
||||
void updateAll() final;
|
||||
|
||||
bool configureProject(const DebuggerRunParameters &rp);
|
||||
|
||||
Utils::FilePaths enabledSourceFiles() const;
|
||||
quint32 currentThreadId() const;
|
||||
quint32 currentFrameLevel() const;
|
||||
|
||||
bool m_simulator = false;
|
||||
bool m_loadingRequired = false;
|
||||
bool m_inUpdateLocals = false;
|
||||
quint64 m_address = 0;
|
||||
UvscClient::Registers m_registers;
|
||||
std::unique_ptr<UvscClient> m_client;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -0,0 +1,382 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvscdatatypes.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QLibrary>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Maximum number of clients UVSC can support.
|
||||
#define UVSC_MAX_CLIENTS 10
|
||||
// Maximum string size.
|
||||
#define UVSC_MAX_API_STR_SIZE 1024
|
||||
// Auto port.
|
||||
#define UVSC_PORT_AUTO 0
|
||||
// Minimum auto port value.
|
||||
#define UVSC_MIN_AUTO_PORT 1
|
||||
// Maximum auto port value.
|
||||
#define UVSC_MAX_AUTO_PORT 65535
|
||||
|
||||
// UVSC status codes.
|
||||
enum UVSC_STATUS {
|
||||
UVSC_STATUS_SUCCESS = 0,
|
||||
UVSC_STATUS_FAILED = 1,
|
||||
UVSC_STATUS_NOT_SUPPORTED = 2,
|
||||
UVSC_STATUS_NOT_INIT = 3,
|
||||
UVSC_STATUS_TIMEOUT = 4,
|
||||
UVSC_STATUS_INVALID_CONTEXT = 5,
|
||||
UVSC_STATUS_INVALID_PARAM = 6,
|
||||
UVSC_STATUS_BUFFER_TOO_SMALL = 7,
|
||||
UVSC_STATUS_CALLBACK_IN_USE = 8,
|
||||
UVSC_STATUS_COMMAND_ERROR = 9,
|
||||
UVSC_STATUS_END
|
||||
};
|
||||
|
||||
// uVision run modes.
|
||||
enum UVSC_RUNMODE {
|
||||
UVSC_RUNMODE_NORMAL = 0,
|
||||
UVSC_RUNMODE_LABVIEW = 1,
|
||||
UVSC_RUNMODE_END = 2,
|
||||
};
|
||||
|
||||
// Progress bar operations.
|
||||
enum UVSC_PBAR {
|
||||
UVSC_PBAR_INIT = 0,
|
||||
UVSC_PBAR_TEXT = 1,
|
||||
UVSC_PBAR_POS = 2,
|
||||
UVSC_PBAR_STOP = 3,
|
||||
};
|
||||
|
||||
// UVSC callback types.
|
||||
enum UVSC_CB_TYPE {
|
||||
UVSC_CB_ERROR = 0,
|
||||
UVSC_CB_ASYNC_MSG = 1,
|
||||
UVSC_CB_DISCONNECTED = 2,
|
||||
UVSC_CB_BUILD_OUTPUT_MSG = 3,
|
||||
UVSC_CB_PROGRESS_BAR_MSG = 4,
|
||||
UVSC_CB_CMD_OUTPUT_MSG = 5,
|
||||
};
|
||||
|
||||
// UVSC callback data.
|
||||
union UVSC_CB_DATA {
|
||||
UVSOCK_CMD msg;
|
||||
UVSC_STATUS error;
|
||||
qint32 connectionHandle;
|
||||
};
|
||||
static_assert(sizeof(UVSC_CB_DATA) == 32800, "UVSC_CB_DATA size is not 32800 bytes");
|
||||
|
||||
// UVSC callback function.
|
||||
typedef void (*uvsc_cb)(void *cb_custom, UVSC_CB_TYPE type, UVSC_CB_DATA *data);
|
||||
|
||||
// UVSC logging callback function.
|
||||
typedef void (*log_cb)(const char *msg, int msgLen);
|
||||
|
||||
// Macro to generate functions && symbols.
|
||||
#define GENERATE_SYMBOL_VARIABLE(returnType, symbolName, ...) \
|
||||
typedef returnType (*fp_##symbolName)(__VA_ARGS__); \
|
||||
static fp_##symbolName symbolName;
|
||||
|
||||
// Macro to resolve functions && symbols.
|
||||
#define RESOLVE_SYMBOL(symbolName) \
|
||||
symbolName = reinterpret_cast<fp_##symbolName>(uvscLibrary->resolve(#symbolName)); \
|
||||
if (!symbolName) \
|
||||
return false;
|
||||
|
||||
// Control functions.
|
||||
GENERATE_SYMBOL_VARIABLE(void, UVSC_Version, quint32 *, quint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_Init, qint32, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_UnInit, void)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_OpenConnection, qint8 *, qint32 *, qint32 *, \
|
||||
qint8 *, UVSC_RUNMODE, uvsc_cb, void *, qint8 *, quint8, log_cb)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_CloseConnection, qint32, quint8)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_ConnHandleFromConnName, qint8 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GetLastError, qint32, \
|
||||
UV_OPERATION *, UV_STATUS *, qint8 *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_LogControl, qint32, quint8, quint8)
|
||||
// Messaging functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_SET_OPTIONS, qint32, UVSOCK_OPTIONS *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_UVSOCK_VERSION, qint32, qint32 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_EXT_VERSION, qint32, EXTVERS *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_HIDE, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_SHOW, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_MAXIMIZE, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_MINIMIZE, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_RESTORE, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_UI_LOCK, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_UI_UNLOCK, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GEN_CHECK_LICENSE, qint32, UVLICINFO *)
|
||||
// Project functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_LOAD, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_CLOSE, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ADD_FILE, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_DEL_FILE, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ENUM_FILES, qint32, SSTR *, \
|
||||
qint32, SSTR *, qint32 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ADD_GROUP, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_DEL_GROUP, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_SET_TARGET, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_SET_OUTPUTNAME, qint32, PRJDATA *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ENUM_GROUPS, qint32, \
|
||||
SSTR *, qint32 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ENUM_TARGETS, qint32, \
|
||||
SSTR *, qint32 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_ACTIVE_FILES, qint32, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_BUILD, qint32, quint8)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_BUILD_CANCEL, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_CLEAN, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_FLASH_DOWNLOAD, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_GET_OPTITEM, qint32, TRNOPT *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_SET_OPTITEM, qint32, TRNOPT *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_GET_DEBUG_TARGET, qint32, DBGTGTOPT *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_SET_DEBUG_TARGET, qint32, DBGTGTOPT *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_CMD_PROGRESS, qint32, PGRESS *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_GET_OUTPUTNAME, qint32, \
|
||||
iPATHREQ *, SSTR *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_PRJ_GET_CUR_TARGET, qint32, \
|
||||
iPATHREQ *, SSTR *, qint32)
|
||||
// Debug functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENTER, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EXIT, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_START_EXECUTION, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_RUN_TO_ADDRESS, qint32, quint64)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STOP_EXECUTION, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STATUS, qint32, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_HLL, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_HLL_N, qint32, quint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_INSTRUCTION, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_INSTRUCTION_N, qint32, quint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_INTO, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_INTO_N, qint32, quint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_STEP_OUT, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_RESET, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_MEM_READ, qint32, AMEM *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_MEM_WRITE, qint32, AMEM *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_CREATE_BP, qint32, \
|
||||
BKPARM *, qint32, BKRSP *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_CHANGE_BP, qint32, \
|
||||
BKCHG *, qint32, BKRSP *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUMERATE_BP, qint32, \
|
||||
BKRSP *, qint32 *, qint32*)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_SERIAL_GET, qint32, SERIO *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_SERIAL_PUT, qint32, SERIO *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_CALC_EXPRESSION, qint32, VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EVAL_WATCH_EXPRESSION, qint32, \
|
||||
VSET *, qint32, VARINFO *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_REMOVE_WATCH_EXPRESSION, qint32, \
|
||||
VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_VARIABLES, qint32, \
|
||||
IVARENUM *, VARINFO *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_VARIABLE_SET, qint32, VARVAL *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_VTR, qint32, \
|
||||
iVTRENUM *, AVTR *, qint32 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_VTR_GET, qint32, VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_VTR_SET, qint32, VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ITM_REGISTER, qint32, ITMOUT *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ITM_UNREGISTER, qint32, ITMOUT *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_STACK, qint32, \
|
||||
iSTKENUM *, STACKENUM *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_TASKS, qint32, TASKENUM *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_MENUS, qint32, \
|
||||
MENUID *, MENUENUM *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_MENU_EXEC, qint32, MENUID *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ADR_TOFILELINE, qint32, \
|
||||
ADRMTFL *, AFLMAP *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ADR_SHOWCODE, qint32, iSHOWSYNC *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_POWERSCALE_SHOWCODE, qint32, UVSC_PSTAMP *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_WAKE, qint32, iINTERVAL *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_SLEEP, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EXEC_CMD, qint32, EXECCMD *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EVAL_EXPRESSION_TO_STR, qint32, \
|
||||
VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_FILELINE_TO_ADR, qint32, \
|
||||
AFLMAP *, qint32, VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_REGISTER_GROUPS, qint32, \
|
||||
SSTR *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_ENUM_REGISTERS, qint32, \
|
||||
REGENUM *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_READ_REGISTERS, qint32, qint8 *, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_REGISTER_SET, qint32, VSET *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_DSM_READ, qint32, AMEM *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EVTR_REGISTER, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EVTR_UNREGISTER, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_DBG_EVTR_ENUMSCVDFILES, qint32, \
|
||||
SSTR *, qint32 *)
|
||||
// Build output functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GetBuildOutputSize, qint32, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GetBuildOutput, qint32, qint8 *, qint32)
|
||||
// Command output functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GetCmdOutputSize, qint32, qint32 *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_GetCmdOutput, qint32, qint8 *, qint32)
|
||||
// Queue functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_ReadBuildQ, qint32, qint8 *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_ReadPBarQ, qint32, \
|
||||
UVSC_PBAR *, qint8 *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_ReadAsyncQ, qint32, \
|
||||
qint32, UVSOCK_CMD *, qint32)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_FlushAsyncQ, qint32, qint32)
|
||||
// Advanced functions.
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_TxRxRaw, qint32, UVSOCK_CMD *)
|
||||
GENERATE_SYMBOL_VARIABLE(UVSC_STATUS, UVSC_CreateMsg, UVSOCK_CMD *, UV_OPERATION, \
|
||||
qint32, const void *)
|
||||
|
||||
inline bool resolveUvscSymbols(const QDir &dir, QLibrary *uvscLibrary)
|
||||
{
|
||||
if (!uvscLibrary->isLoaded()) {
|
||||
#ifdef Q_PROCESSOR_X86_64
|
||||
uvscLibrary->setFileName(dir.absoluteFilePath(QStringLiteral("uvsc64")));
|
||||
#else
|
||||
uvscLibrary->setFileName(dir.absoluteFilePath(QStringLiteral("uvsc")));
|
||||
#endif
|
||||
if (!uvscLibrary->load())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Control functions.
|
||||
RESOLVE_SYMBOL(UVSC_Version)
|
||||
RESOLVE_SYMBOL(UVSC_Init)
|
||||
RESOLVE_SYMBOL(UVSC_UnInit)
|
||||
RESOLVE_SYMBOL(UVSC_OpenConnection)
|
||||
RESOLVE_SYMBOL(UVSC_CloseConnection)
|
||||
RESOLVE_SYMBOL(UVSC_ConnHandleFromConnName)
|
||||
RESOLVE_SYMBOL(UVSC_GetLastError)
|
||||
RESOLVE_SYMBOL(UVSC_LogControl)
|
||||
// Messaging functions.
|
||||
RESOLVE_SYMBOL(UVSC_GEN_SET_OPTIONS)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_UVSOCK_VERSION)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_EXT_VERSION)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_HIDE)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_SHOW)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_MAXIMIZE)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_MINIMIZE)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_RESTORE)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_UI_LOCK)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_UI_UNLOCK)
|
||||
RESOLVE_SYMBOL(UVSC_GEN_CHECK_LICENSE)
|
||||
// Project functions.
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_LOAD)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_CLOSE)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ADD_FILE)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_DEL_FILE)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ENUM_FILES)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ADD_GROUP)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_DEL_GROUP)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_SET_TARGET)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_SET_OUTPUTNAME)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ENUM_GROUPS)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ENUM_TARGETS)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_ACTIVE_FILES)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_BUILD)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_BUILD_CANCEL)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_CLEAN)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_FLASH_DOWNLOAD)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_GET_OPTITEM)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_SET_OPTITEM)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_GET_DEBUG_TARGET)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_SET_DEBUG_TARGET)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_CMD_PROGRESS)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_GET_OUTPUTNAME)
|
||||
RESOLVE_SYMBOL(UVSC_PRJ_GET_CUR_TARGET)
|
||||
// Debug functions.
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENTER)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EXIT)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_START_EXECUTION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_RUN_TO_ADDRESS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STOP_EXECUTION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STATUS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_HLL)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_HLL_N)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_INSTRUCTION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_INSTRUCTION_N)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_INTO)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_INTO_N)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_STEP_OUT)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_RESET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_MEM_READ)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_MEM_WRITE)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_CREATE_BP)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_CHANGE_BP)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUMERATE_BP)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_SERIAL_GET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_SERIAL_PUT)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_CALC_EXPRESSION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EVAL_WATCH_EXPRESSION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_REMOVE_WATCH_EXPRESSION)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_VARIABLES)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_VARIABLE_SET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_VTR)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_VTR_GET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_VTR_SET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ITM_REGISTER)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ITM_UNREGISTER)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_STACK)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_TASKS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_MENUS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_MENU_EXEC)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ADR_TOFILELINE)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ADR_SHOWCODE)
|
||||
RESOLVE_SYMBOL(UVSC_POWERSCALE_SHOWCODE)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_WAKE)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_SLEEP)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EXEC_CMD)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EVAL_EXPRESSION_TO_STR)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_FILELINE_TO_ADR)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_REGISTER_GROUPS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_ENUM_REGISTERS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_READ_REGISTERS)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_REGISTER_SET)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_DSM_READ)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EVTR_REGISTER)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EVTR_UNREGISTER)
|
||||
RESOLVE_SYMBOL(UVSC_DBG_EVTR_ENUMSCVDFILES)
|
||||
// Build output functions.
|
||||
RESOLVE_SYMBOL(UVSC_GetBuildOutputSize)
|
||||
RESOLVE_SYMBOL(UVSC_GetBuildOutput)
|
||||
// Command output functions.
|
||||
RESOLVE_SYMBOL(UVSC_GetCmdOutputSize)
|
||||
RESOLVE_SYMBOL(UVSC_GetCmdOutput)
|
||||
// Queue functions.
|
||||
RESOLVE_SYMBOL(UVSC_ReadBuildQ)
|
||||
RESOLVE_SYMBOL(UVSC_ReadPBarQ)
|
||||
RESOLVE_SYMBOL(UVSC_ReadAsyncQ)
|
||||
RESOLVE_SYMBOL(UVSC_FlushAsyncQ)
|
||||
// Advanced functions.
|
||||
RESOLVE_SYMBOL(UVSC_TxRxRaw)
|
||||
RESOLVE_SYMBOL(UVSC_CreateMsg)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,345 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "uvscutils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QVariant>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
namespace UvscUtils {
|
||||
|
||||
// Utils
|
||||
|
||||
SSTR encodeSstr(const QString &value)
|
||||
{
|
||||
SSTR sstr = {};
|
||||
// Note: UVSC API support only ASCII!
|
||||
const QByteArray data = value.toLocal8Bit();
|
||||
if (sizeof(sstr.data) < size_t(data.size()))
|
||||
return sstr;
|
||||
sstr.length = data.size();
|
||||
::memcpy(sstr.data, data.constData(), sstr.length);
|
||||
return sstr;
|
||||
}
|
||||
|
||||
QString decodeSstr(const SSTR &sstr)
|
||||
{
|
||||
// Note: UVSC API support only ASCII!
|
||||
return QString::fromLocal8Bit(reinterpret_cast<const char *>(sstr.data),
|
||||
sstr.length);
|
||||
}
|
||||
|
||||
QString decodeAscii(const qint8 *ascii)
|
||||
{
|
||||
// Note: UVSC API support only ASCII!
|
||||
return QString::fromLocal8Bit(reinterpret_cast<const char *>(ascii));
|
||||
}
|
||||
|
||||
QByteArray encodeProjectData(const QStringList &someNames)
|
||||
{
|
||||
QByteArray buffer(sizeof(PRJDATA) - 1, 0);
|
||||
|
||||
// Note: UVSC API support only ASCII!
|
||||
quint32 namesLength = 0;
|
||||
for (const QString &someName : someNames) {
|
||||
const QByteArray asciiName = someName.toLocal8Bit();
|
||||
buffer.append(asciiName);
|
||||
buffer.append('\0');
|
||||
namesLength += asciiName.size() + 1;
|
||||
}
|
||||
buffer.append('\0');
|
||||
namesLength += 1;
|
||||
|
||||
const auto dataPtr = reinterpret_cast<PRJDATA *>(buffer.data());
|
||||
dataPtr->code = 0;
|
||||
dataPtr->length = namesLength;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd)
|
||||
{
|
||||
QByteArray buffer(sizeof(BKPARM) - 1, 0);
|
||||
// Note: UVSC API support only ASCII!
|
||||
const QByteArray asciiExp = exp.toLocal8Bit();
|
||||
buffer.append(asciiExp);
|
||||
buffer.append('\0');
|
||||
const QByteArray asciiCmd = cmd.toLocal8Bit();
|
||||
buffer.append(asciiCmd);
|
||||
buffer.append('\0');
|
||||
|
||||
const auto bkPtr = reinterpret_cast<BKPARM *>(buffer.data());
|
||||
bkPtr->type = type;
|
||||
bkPtr->count = 1;
|
||||
bkPtr->accessSize = 0;
|
||||
bkPtr->expressionLength = asciiExp.count() + 1;
|
||||
bkPtr->commandLength = asciiCmd.count() + 1;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
QByteArray encodeAmem(quint64 address, quint32 bytesCount)
|
||||
{
|
||||
QByteArray buffer(sizeof(AMEM) - 1, 0);
|
||||
buffer.resize(buffer.size() + bytesCount);
|
||||
const auto amem = reinterpret_cast<AMEM *>(buffer.data());
|
||||
amem->address = address;
|
||||
amem->bytesCount = bytesCount;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
TVAL encodeVoidTval()
|
||||
{
|
||||
TVAL tval = {};
|
||||
tval.type = VTT_void;
|
||||
return tval;
|
||||
}
|
||||
|
||||
TVAL encodeIntTval(int value)
|
||||
{
|
||||
TVAL tval = {};
|
||||
tval.type = VTT_int;
|
||||
tval.v.i = value;
|
||||
return tval;
|
||||
}
|
||||
|
||||
TVAL encodeU64Tval(quint64 value)
|
||||
{
|
||||
TVAL tval = {};
|
||||
tval.type = VTT_uint64;
|
||||
tval.v.u64 = value;
|
||||
return tval;
|
||||
}
|
||||
|
||||
VSET encodeVoidVset(const QString &value)
|
||||
{
|
||||
VSET vset = {};
|
||||
vset.value = encodeVoidTval();
|
||||
vset.name = encodeSstr(value);
|
||||
return vset;
|
||||
}
|
||||
|
||||
VSET encodeIntVset(int index, const QString &value)
|
||||
{
|
||||
VSET vset = {};
|
||||
vset.value = encodeIntTval(index);
|
||||
vset.name = encodeSstr(value);
|
||||
return vset;
|
||||
}
|
||||
|
||||
VSET encodeU64Vset(quint64 index, const QString &value)
|
||||
{
|
||||
VSET vset = {};
|
||||
vset.value = encodeU64Tval(index);
|
||||
vset.name = encodeSstr(value);
|
||||
return vset;
|
||||
}
|
||||
|
||||
bool isKnownRegister(int type)
|
||||
{
|
||||
if (type >= MinimumGeneralPurposeRegister && type <= MaximumGeneralPurposeRegister)
|
||||
return true;
|
||||
else if (type >= MinimumBankedRegister && type <= MaximumBankedRegister)
|
||||
return true;
|
||||
else if (type >= MinimumSystemRegister && type <= MaximumSystemRegister)
|
||||
return true;
|
||||
else if (type == ProgramStatusRegister)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString adjustHexValue(QString hex, const QString &type)
|
||||
{
|
||||
if (!hex.startsWith("0x"))
|
||||
return hex;
|
||||
|
||||
hex.remove(0, 2);
|
||||
const QByteArray data = QByteArray::fromHex(hex.toLatin1());
|
||||
QDataStream in(data);
|
||||
|
||||
if (type == "float") {
|
||||
float v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else if (type == "double") {
|
||||
double v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else {
|
||||
const bool isUnsigned = type.startsWith("unsigned");
|
||||
switch (data.count()) {
|
||||
case 1:
|
||||
if (isUnsigned) {
|
||||
quint8 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else {
|
||||
qint8 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
}
|
||||
case 2:
|
||||
if (isUnsigned) {
|
||||
quint16 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else {
|
||||
qint16 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
}
|
||||
case 4:
|
||||
if (isUnsigned) {
|
||||
quint32 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else {
|
||||
qint32 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
}
|
||||
case 8:
|
||||
if (isUnsigned) {
|
||||
quint64 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
} else {
|
||||
qint64 v = 0;
|
||||
in >> v;
|
||||
return QString::number(v);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QString buildLocalId(const VARINFO &varinfo)
|
||||
{
|
||||
return QString::number(varinfo.id);
|
||||
}
|
||||
|
||||
QString buildLocalEditable(const VARINFO &varinfo)
|
||||
{
|
||||
return QVariant(bool(varinfo.isEditable)).toString();
|
||||
}
|
||||
|
||||
QString buildLocalNumchild(const VARINFO &varinfo)
|
||||
{
|
||||
return QString::number(varinfo.count);
|
||||
}
|
||||
|
||||
QString buildLocalName(const VARINFO &varinfo)
|
||||
{
|
||||
return decodeSstr(varinfo.name);
|
||||
}
|
||||
|
||||
QString buildLocalIName(const QString &parentIName, const QString &name)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return parentIName;
|
||||
return parentIName + '.' + name;
|
||||
}
|
||||
|
||||
QString buildLocalWName(const QString &exp)
|
||||
{
|
||||
return QString::fromLatin1(exp.toLatin1().toHex());
|
||||
}
|
||||
|
||||
QString buildLocalType(const VARINFO &varinfo)
|
||||
{
|
||||
QString type = decodeSstr(varinfo.type);
|
||||
// Remove the 'auto - ' and 'param - ' prefixes.
|
||||
if (type.startsWith("auto - "))
|
||||
type.remove(0, 7);
|
||||
else if (type.startsWith("param - "))
|
||||
type.remove(0, 8);
|
||||
return type;
|
||||
}
|
||||
|
||||
QString buildLocalValue(const VARINFO &varinfo, const QString &type)
|
||||
{
|
||||
QString value = decodeSstr(varinfo.value);
|
||||
// Adjust value to the desired form.
|
||||
if (value.startsWith("0x")) {
|
||||
const int spaceIndex = value.indexOf(" ");
|
||||
const QString hex = value.mid(0, spaceIndex);
|
||||
if (type == "char") {
|
||||
value = adjustHexValue(hex, type);
|
||||
} else if (type.startsWith("enum") && spaceIndex != -1) {
|
||||
const QString name = value.mid(spaceIndex + 1);
|
||||
value = QStringLiteral("%1 (%2)").arg(name).arg(hex.toInt(nullptr, 16));
|
||||
} else if (type.startsWith("struct")) {
|
||||
value = QStringLiteral("@%1").arg(hex);
|
||||
} else {
|
||||
value = adjustHexValue(hex, type);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
GdbMi buildEntry(const QString &name, const QString &data, GdbMi::Type type)
|
||||
{
|
||||
GdbMi result;
|
||||
result.m_name = name;
|
||||
result.m_data = data;
|
||||
result.m_type = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
GdbMi buildChildrenEntry(const std::vector<GdbMi> &locals)
|
||||
{
|
||||
GdbMi children = buildEntry("children", "", GdbMi::List);
|
||||
for (const GdbMi &local : locals)
|
||||
children.addChild(local);
|
||||
return children;
|
||||
}
|
||||
|
||||
GdbMi buildResultTemplateEntry(bool partial)
|
||||
{
|
||||
GdbMi all = UvscUtils::buildEntry("result", "", GdbMi::Tuple);
|
||||
|
||||
// FIXME: Do we need in 'token', 'typeinfo', 'counts' and 'timings'
|
||||
// entries?
|
||||
|
||||
// Build token entry.
|
||||
all.addChild(UvscUtils::buildEntry("token", "0", GdbMi::Const));
|
||||
// Build typeinfo entry.
|
||||
all.addChild(UvscUtils::buildEntry("typeinfo", "", GdbMi::List));
|
||||
// Build counts entry.
|
||||
all.addChild(UvscUtils::buildEntry("counts", "", GdbMi::Tuple));
|
||||
// Build timings entry.
|
||||
all.addChild(UvscUtils::buildEntry("timings", "", GdbMi::List));
|
||||
// Build partial entry.
|
||||
all.addChild(UvscUtils::buildEntry("partial", QString::number(partial),
|
||||
GdbMi::Const));
|
||||
return all;
|
||||
}
|
||||
|
||||
} // namespace UvscUtils
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Denis Shienkov <denis.shienkov@gmail.com>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "uvscfunctions.h"
|
||||
|
||||
#include <debugger/debuggerprotocol.h>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
namespace UvscUtils {
|
||||
|
||||
enum RegisterType {
|
||||
// General purpose registers (R0-R15).
|
||||
MinimumGeneralPurposeRegister = 0,
|
||||
MaximumGeneralPurposeRegister = 15,
|
||||
|
||||
// Banked registers.
|
||||
MinimumBankedRegister = 17,
|
||||
MaximumBankedRegister = 18,
|
||||
|
||||
// System registers.
|
||||
MinimumSystemRegister = 32,
|
||||
MaximumSystemRegister = 35,
|
||||
|
||||
// Program status register.
|
||||
ProgramStatusRegister = 256,
|
||||
};
|
||||
|
||||
SSTR encodeSstr(const QString &value);
|
||||
QString decodeSstr(const SSTR &sstr);
|
||||
QString decodeAscii(const qint8 *ascii);
|
||||
QByteArray encodeProjectData(const QStringList &someNames);
|
||||
QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd = QString());
|
||||
QByteArray encodeAmem(quint64 address, quint32 bytesCount);
|
||||
TVAL encodeVoidTval();
|
||||
TVAL encodeIntTval(int value);
|
||||
TVAL encodeU64Tval(quint64 value);
|
||||
VSET encodeVoidVset(const QString &value);
|
||||
VSET encodeIntVset(int index, const QString &value);
|
||||
VSET encodeU64Vset(quint64 index, const QString &value);
|
||||
bool isKnownRegister(int type);
|
||||
QString adjustHexValue(QString hex, const QString &type);
|
||||
|
||||
QString buildLocalId(const VARINFO &varinfo);
|
||||
QString buildLocalEditable(const VARINFO &varinfo);
|
||||
QString buildLocalNumchild(const VARINFO &varinfo);
|
||||
QString buildLocalName(const VARINFO &varinfo);
|
||||
QString buildLocalIName(const QString &parentIName, const QString &name = QString());
|
||||
QString buildLocalWName(const QString &exp);
|
||||
QString buildLocalType(const VARINFO &varinfo);
|
||||
QString buildLocalValue(const VARINFO &varinfo, const QString &type);
|
||||
|
||||
GdbMi buildEntry(const QString &name, const QString &data, GdbMi::Type type);
|
||||
GdbMi buildChildrenEntry(const std::vector<GdbMi> &locals);
|
||||
GdbMi buildResultTemplateEntry(bool partial);
|
||||
|
||||
} // namespace UvscUtils
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -317,6 +317,11 @@ void WatchItem::parseHelper(const GdbMi &input, bool maySort)
|
||||
editformat = input["editformat"].data();
|
||||
editencoding = DebuggerEncoding(input["editencoding"].data());
|
||||
|
||||
// We need it for UVSC engine!
|
||||
mi = input["id"];
|
||||
if (mi.isValid())
|
||||
id = mi.toInt();
|
||||
|
||||
mi = input["valueelided"];
|
||||
if (mi.isValid())
|
||||
elided = mi.toInt();
|
||||
|
||||
+1
-1
Submodule src/shared/qbs updated: fa73a6da5a...f8c9a663fb
Reference in New Issue
Block a user