diff --git a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp index bee1f72bad1..2e0c6a2e778 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp @@ -201,8 +201,12 @@ bool UvscServerProvider::aboutToRun(DebuggerRunTool *runTool, QString &errorMess if (!optFilePath.exists()) return false; + const FilePath peripheralDescriptionFile = FilePath::fromString(m_deviceSelection.svd); + Runnable inferior; inferior.executable = bin; + inferior.extraData.insert(Debugger::Constants::kPeripheralDescriptionFile, + peripheralDescriptionFile.toVariant()); inferior.extraData.insert(Debugger::Constants::kUVisionProjectFilePath, projFilePath.toString()); inferior.extraData.insert(Debugger::Constants::kUVisionOptionsFilePath, optFilePath.toString()); inferior.extraData.insert(Debugger::Constants::kUVisionSimulator, isSimulator()); diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp index 391b0a4d158..e39d2789336 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp @@ -497,6 +497,14 @@ DeviceSelection DeviceSelectionView::buildSelection(const DeviceSelectionItem *i break; } } while ((item = item->parentPackItem())); + + // Fix relative SVD file path to make it as absolute. + const QFileInfo fi(selection.svd); + if (!fi.isAbsolute()) { + const QDir dir(QFileInfo(selection.package.file).path()); + selection.svd = QFileInfo(dir, fi.filePath()).absoluteFilePath(); + } + return selection; } diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp index 84436d3b651..6f9866e8b9d 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp @@ -27,6 +27,8 @@ #include "uvtargetdevicemodel.h" #include "uvtargetdeviceviewer.h" +#include + #include #include #include @@ -83,6 +85,14 @@ DeviceSelectorDetailsPanel::DeviceSelectorDetailsPanel(DeviceSelection &selectio layout->addRow(tr("Memory:"), m_memoryView); m_algorithmView = new DeviceSelectionAlgorithmView(m_selection); layout->addRow(tr("Flash algorithm"), m_algorithmView); + m_peripheralDescriptionFileChooser = new Utils::PathChooser(this); + m_peripheralDescriptionFileChooser->setExpectedKind(Utils::PathChooser::File); + m_peripheralDescriptionFileChooser->setPromptDialogFilter( + tr("Peripheral description files (*.svd)")); + m_peripheralDescriptionFileChooser->setPromptDialogTitle( + tr("Select Peripheral Description File")); + layout->addRow(tr("Peripheral description file:"), + m_peripheralDescriptionFileChooser); setLayout(layout); refresh(); @@ -95,6 +105,8 @@ DeviceSelectorDetailsPanel::DeviceSelectorDetailsPanel(DeviceSelection &selectio m_selection.algorithmIndex = index; emit selectionChanged(); }); + connect(m_peripheralDescriptionFileChooser, &Utils::PathChooser::pathChanged, + this, &DeviceSelectorDetailsPanel::selectionChanged); } static QString trimVendor(const QString &vendor) @@ -111,6 +123,7 @@ void DeviceSelectorDetailsPanel::refresh() m_memoryView->refresh(); m_algorithmView->refresh(); m_algorithmView->setAlgorithm(m_selection.algorithmIndex); + m_peripheralDescriptionFileChooser->setPath(m_selection.svd); } // DeviceSelector diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h index abc00e9c1c7..d65bc64153e 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h @@ -38,6 +38,8 @@ class QLineEdit; class QPlainTextEdit; QT_END_NAMESPACE +namespace Utils { class PathChooser; } + namespace BareMetal { namespace Internal { namespace Uv { @@ -107,6 +109,7 @@ private: QPlainTextEdit *m_descEdit = nullptr; DeviceSelectionMemoryView *m_memoryView = nullptr; DeviceSelectionAlgorithmView *m_algorithmView = nullptr; + Utils::PathChooser *m_peripheralDescriptionFileChooser = nullptr; }; // DeviceSelectionDialog diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp index 57de522689a..b0feca3c776 100644 --- a/src/plugins/debugger/uvsc/uvscclient.cpp +++ b/src/plugins/debugger/uvsc/uvscclient.cpp @@ -691,6 +691,41 @@ bool UvscClient::inspectWatcher(const QStringList &expandedWatcherINames, return true; } +bool UvscClient::fetchMemory(quint64 address, QByteArray &data) +{ + if (data.isEmpty()) + data.resize(sizeof(quint8)); + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_READ(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + data = QByteArray(reinterpret_cast(&amemPtr->bytes), + amemPtr->bytesCount); + return true; +} + +bool UvscClient::changeMemory(quint64 address, const QByteArray &data) +{ + if (data.isEmpty()) { + setError(RuntimeError); + return false; + } + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_WRITE(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + return true; +} + bool UvscClient::disassemblyAddress(quint64 address, QByteArray &result) { if (!checkConnection()) diff --git a/src/plugins/debugger/uvsc/uvscclient.h b/src/plugins/debugger/uvsc/uvscclient.h index a602622a2b2..a1fed713092 100644 --- a/src/plugins/debugger/uvsc/uvscclient.h +++ b/src/plugins/debugger/uvsc/uvscclient.h @@ -87,6 +87,9 @@ public: bool fetchWatchers(const QStringList &expandedWatcherINames, const std::vector> &rootWatchers, GdbMi &data); + bool fetchMemory(quint64 address, QByteArray &data); + bool changeMemory(quint64 address, const QByteArray &data); + bool disassemblyAddress(quint64 address, QByteArray &result); bool setRegisterValue(int index, const QString &value); diff --git a/src/plugins/debugger/uvsc/uvscengine.cpp b/src/plugins/debugger/uvsc/uvscengine.cpp index 3938972d6f4..267dddee08d 100644 --- a/src/plugins/debugger/uvsc/uvscengine.cpp +++ b/src/plugins/debugger/uvsc/uvscengine.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -162,6 +163,9 @@ void UvscEngine::setupEngine() if (!configureProject(rp)) return; + + // Reload peripheral register description. + peripheralRegisterHandler()->updateRegisterGroups(); } void UvscEngine::runEngine() @@ -231,6 +235,14 @@ void UvscEngine::setRegisterValue(const QString &name, const QString &value) reloadRegisters(); } +void UvscEngine::setPeripheralRegisterValue(quint64 address, quint64 value) +{ + const QByteArray data = UvscUtils::encodeU32(value); + if (!m_client->changeMemory(address, data)) + return; + reloadPeripheralRegisters(); +} + void UvscEngine::executeStepOver(bool byInstruction) { notifyInferiorRunRequested(); @@ -332,6 +344,7 @@ void UvscEngine::activateFrame(int index) gotoCurrentLocation(); updateLocals(); reloadRegisters(); + reloadPeripheralRegisters(); } bool UvscEngine::stateAcceptsBreakpointChanges() const @@ -469,6 +482,17 @@ void UvscEngine::reloadRegisters() handleReloadRegisters(); } +void UvscEngine::reloadPeripheralRegisters() +{ + if (!isPeripheralRegistersWindowVisible()) + return; + + const QList addresses = peripheralRegisterHandler()->activeRegisters(); + if (addresses.isEmpty()) + return; // Nothing to update. + handleReloadPeripheralRegisters(addresses); +} + void UvscEngine::reloadFullStack() { resetLocation(); @@ -496,6 +520,7 @@ void UvscEngine::updateAll() handleThreadInfo(); reloadRegisters(); + reloadPeripheralRegisters(); updateLocals(); } @@ -653,6 +678,7 @@ void UvscEngine::handleReloadStack(bool isFull) if (!m_client->fetchStackFrames(taskId, m_address, data)) { m_address = 0; reloadRegisters(); + reloadPeripheralRegisters(); return; } @@ -678,6 +704,19 @@ void UvscEngine::handleReloadRegisters() } } +void UvscEngine::handleReloadPeripheralRegisters(const QList &addresses) +{ + for (const quint64 address : addresses) { + QByteArray data = UvscUtils::encodeU32(0); + if (!m_client->fetchMemory(address, data)) { + showMessage(tr("UVSC: Fetching peripheral register failed"), LogMisc); + } else { + const quint32 value = UvscUtils::decodeU32(data); + peripheralRegisterHandler()->updateRegister(address, value); + } + } +} + void UvscEngine::handleUpdateLocals(bool partial) { m_inUpdateLocals = false; diff --git a/src/plugins/debugger/uvsc/uvscengine.h b/src/plugins/debugger/uvsc/uvscengine.h index 97f843f44cb..ace70fd5c56 100644 --- a/src/plugins/debugger/uvsc/uvscengine.h +++ b/src/plugins/debugger/uvsc/uvscengine.h @@ -49,6 +49,7 @@ public: bool hasCapability(unsigned cap) const final; void setRegisterValue(const QString &name, const QString &value) final; + void setPeripheralRegisterValue(quint64 address, quint64 value) final; void executeStepOver(bool byInstruction) final; void executeStepIn(bool byInstruction) final; @@ -72,6 +73,8 @@ public: void fetchDisassembler(DisassemblerAgent *agent) final; void reloadRegisters() final; + void reloadPeripheralRegisters() final; + void reloadFullStack() final; private slots: @@ -84,6 +87,7 @@ private slots: void handleThreadInfo(); void handleReloadStack(bool isFull); void handleReloadRegisters(); + void handleReloadPeripheralRegisters(const QList &addresses); void handleUpdateLocals(bool partial); void handleInsertBreakpoint(const QString &exp, const Breakpoint &bp); void handleRemoveBreakpoint(const Breakpoint &bp); diff --git a/src/plugins/debugger/uvsc/uvscutils.cpp b/src/plugins/debugger/uvsc/uvscutils.cpp index e3b7e8799ac..d7fb4d22eff 100644 --- a/src/plugins/debugger/uvsc/uvscutils.cpp +++ b/src/plugins/debugger/uvsc/uvscutils.cpp @@ -110,6 +110,16 @@ QByteArray encodeAmem(quint64 address, quint32 bytesCount) return buffer; } +QByteArray encodeAmem(quint64 address, const QByteArray &data) +{ + QByteArray buffer(sizeof(AMEM) - 1, 0); + buffer.append(data); + const auto amem = reinterpret_cast(buffer.data()); + amem->address = address; + amem->bytesCount = data.size(); + return buffer; +} + TVAL encodeVoidTval() { TVAL tval = {}; @@ -238,6 +248,24 @@ QString adjustHexValue(QString hex, const QString &type) return {}; } +QByteArray encodeU32(quint32 value) +{ + QByteArray data; + QDataStream out(&data, QIODevice::WriteOnly); + out.setByteOrder(QDataStream::LittleEndian); + out << value; + return data; +} + +quint32 decodeU32(const QByteArray &data) +{ + QDataStream in(data); + in.setByteOrder(QDataStream::LittleEndian); + quint32 value = 0; + in >> value; + return value; +} + QString buildLocalId(const VARINFO &varinfo) { return QString::number(varinfo.id); diff --git a/src/plugins/debugger/uvsc/uvscutils.h b/src/plugins/debugger/uvsc/uvscutils.h index 62959128399..b51ac017a5a 100644 --- a/src/plugins/debugger/uvsc/uvscutils.h +++ b/src/plugins/debugger/uvsc/uvscutils.h @@ -56,6 +56,7 @@ 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); +QByteArray encodeAmem(quint64 address, const QByteArray &data); TVAL encodeVoidTval(); TVAL encodeIntTval(int value); TVAL encodeU64Tval(quint64 value); @@ -65,6 +66,9 @@ VSET encodeU64Vset(quint64 index, const QString &value); bool isKnownRegister(int type); QString adjustHexValue(QString hex, const QString &type); +QByteArray encodeU32(quint32 value); +quint32 decodeU32(const QByteArray &data); + QString buildLocalId(const VARINFO &varinfo); QString buildLocalEditable(const VARINFO &varinfo); QString buildLocalNumchild(const VARINFO &varinfo);