forked from qt-creator/qt-creator
Debugger: Add peripheral registers description file support
This feature is useful for the bare-metal programming. It allows to view the peripheral registers of the debugged device using the GDB. An information about the peripheral registers for a concrete device contains in a special SVD file. A format of this file described e.g. here: * https://www.keil.com/pack/doc/CMSIS/SVD/html/svd_Format_pg.html This feature supported only for ARM devices, and an appropriate SVD files can be found in the Internet, also this files provides by KEIL or IAR EW IDE's. A use case in QtC is that the user should to choose desired SVD file and set its path to the bare-metal device configuration widget. After this, the user can enable the "Peripheral Registers" view, choose a desired register group and to see a peripheral register values. Currently the following basic features are implemented: * Choosing SVD file for a target bare-metal device. * Choosing any peripheral register group, which is available for this device. * Seeing the info about the each peripheral register and its fields. * Seeing the value for the each peripheral register and its fields. * Changing the value for the each peripheral register and its fields (if it is allowed by access for a concrete register or field). * Changing the format of the values (hexadecimal, decimal, octal, binary). Fixes: QTCREATORBUG-18729 Change-Id: I3c38ea50ccd2e128746458f9b918095b4c2d644a Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1030,6 +1030,7 @@ void GdbEngine::updateAll()
|
||||
stackHandler()->setCurrentIndex(0);
|
||||
runCommand({"-thread-info", CB(handleThreadInfo)});
|
||||
reloadRegisters();
|
||||
reloadPeripheralRegisters();
|
||||
updateLocals();
|
||||
}
|
||||
|
||||
@@ -2903,6 +2904,7 @@ void GdbEngine::handleStackListFrames(const DebuggerResponse &response, bool isF
|
||||
// logStreamOutput: "Previous frame identical to this frame (corrupt stack?)\n"
|
||||
//qDebug() << "LISTING STACK FAILED: " << response.toString();
|
||||
reloadRegisters();
|
||||
reloadPeripheralRegisters();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2943,6 +2945,7 @@ void GdbEngine::activateFrame(int frameIndex)
|
||||
|
||||
updateLocals();
|
||||
reloadRegisters();
|
||||
reloadPeripheralRegisters();
|
||||
}
|
||||
|
||||
void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
|
||||
@@ -3062,6 +3065,22 @@ void GdbEngine::reloadRegisters()
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::reloadPeripheralRegisters()
|
||||
{
|
||||
if (!isPeripheralRegistersWindowVisible())
|
||||
return;
|
||||
|
||||
const QList<quint64> addresses = peripheralRegisterHandler()->activeRegisters();
|
||||
if (addresses.isEmpty())
|
||||
return; // Nothing to update.
|
||||
|
||||
for (const quint64 address : addresses) {
|
||||
const QString fun = QStringLiteral("x/1u 0x%1")
|
||||
.arg(QString::number(address, 16));
|
||||
runCommand({fun, CB(handlePeripheralRegisterListValues)});
|
||||
}
|
||||
}
|
||||
|
||||
static QString readWord(const QString &ba, int *pos)
|
||||
{
|
||||
const int n = ba.size();
|
||||
@@ -3127,6 +3146,15 @@ void GdbEngine::setRegisterValue(const QString &name, const QString &value)
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
void GdbEngine::setPeripheralRegisterValue(quint64 address, quint64 value)
|
||||
{
|
||||
const QString fun = QStringLiteral("set {int}0x%1=%2")
|
||||
.arg(QString::number(address, 16))
|
||||
.arg(value);
|
||||
runCommand({fun});
|
||||
reloadPeripheralRegisters();
|
||||
}
|
||||
|
||||
void GdbEngine::handleRegisterListNames(const DebuggerResponse &response)
|
||||
{
|
||||
if (response.resultClass != ResultDone) {
|
||||
@@ -3227,6 +3255,28 @@ void GdbEngine::handleRegisterListValues(const DebuggerResponse &response)
|
||||
handler->commitUpdates();
|
||||
}
|
||||
|
||||
void GdbEngine::handlePeripheralRegisterListValues(
|
||||
const DebuggerResponse &response)
|
||||
{
|
||||
if (response.resultClass != ResultDone)
|
||||
return;
|
||||
|
||||
const QString output = response.consoleStreamOutput;
|
||||
// Regexp to match for '0x50060800:\t0\n'.
|
||||
const QRegularExpression re("^(0x[0-9A-F]+):\\t(\\d+)\\n$");
|
||||
const QRegularExpressionMatch m = re.match(output);
|
||||
if (!m.hasMatch())
|
||||
return;
|
||||
enum { AddressMatch = 1, ValueMatch = 2 };
|
||||
bool aok = false;
|
||||
bool vok = false;
|
||||
const quint64 address = m.captured(AddressMatch).toULongLong(&aok, 16);
|
||||
const quint64 value = m.captured(ValueMatch).toULongLong(&vok, 10);
|
||||
if (!aok || !vok)
|
||||
return;
|
||||
|
||||
peripheralRegisterHandler()->updateRegister(address, value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -3703,6 +3753,9 @@ void GdbEngine::setupEngine()
|
||||
runCommand({commands});
|
||||
|
||||
runCommand({"loadDumpers", CB(handlePythonSetup)});
|
||||
|
||||
// Reload peripheral register description.
|
||||
peripheralRegisterHandler()->updateRegisterGroups();
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbStartFailed()
|
||||
|
||||
Reference in New Issue
Block a user