Trk: Support for frameless protocol.

This commit is contained in:
Friedemann Kleint
2009-08-20 11:30:10 +02:00
parent d774393a86
commit 13cd43773d
7 changed files with 121 additions and 45 deletions

View File

@@ -127,9 +127,10 @@ static inline void dumpRegister(int n, uint value, QByteArray &a)
} }
struct AdapterOptions { struct AdapterOptions {
AdapterOptions() : verbose(1),registerEndianness(LittleEndian),useSocket(false) {} AdapterOptions() : verbose(1),serialFrame(true),registerEndianness(LittleEndian),useSocket(false) {}
int verbose; int verbose;
bool serialFrame;
Endianness registerEndianness; Endianness registerEndianness;
bool useSocket; bool useSocket;
QString gdbServer; QString gdbServer;
@@ -148,6 +149,7 @@ public:
void setGdbServerName(const QString &name); void setGdbServerName(const QString &name);
void setTrkServerName(const QString &name) { m_trkServerName = name; } void setTrkServerName(const QString &name) { m_trkServerName = name; }
void setVerbose(int verbose) { m_verbose = verbose; } void setVerbose(int verbose) { m_verbose = verbose; }
void setSerialFrame(bool b) { m_serialFrame = b; }
void setRegisterEndianness(Endianness r) { m_registerEndianness = r; } void setRegisterEndianness(Endianness r) { m_registerEndianness = r; }
void setUseSocket(bool s) { m_useSocket = s; } void setUseSocket(bool s) { m_useSocket = s; }
bool startServer(); bool startServer();
@@ -261,6 +263,7 @@ private:
int m_verbose; int m_verbose;
Endianness m_registerEndianness; Endianness m_registerEndianness;
bool m_useSocket; bool m_useSocket;
bool m_serialFrame;
bool m_startInferiorTriggered; bool m_startInferiorTriggered;
}; };
@@ -277,6 +280,7 @@ Adapter::Adapter() :
m_verbose(1), m_verbose(1),
m_registerEndianness(LittleEndian), m_registerEndianness(LittleEndian),
m_useSocket(false), m_useSocket(false),
m_serialFrame(true),
m_startInferiorTriggered(false) m_startInferiorTriggered(false)
{ {
startTimer(100); startTimer(100);
@@ -1012,7 +1016,7 @@ void Adapter::tryTrkWrite()
void Adapter::trkWrite(const TrkMessage &msg) void Adapter::trkWrite(const TrkMessage &msg)
{ {
QByteArray ba = frameMessage(msg.code, msg.token, msg.data); QByteArray ba = frameMessage(msg.code, msg.token, msg.data, m_serialFrame);
m_writtenTrkMessages.insert(msg.token, msg); m_writtenTrkMessages.insert(msg.token, msg);
m_trkWriteBusy = true; m_trkWriteBusy = true;
@@ -1071,7 +1075,7 @@ void Adapter::tryTrkRead()
} }
while (!m_trkReadQueue.isEmpty()) while (!m_trkReadQueue.isEmpty())
handleResult(extractResult(&m_trkReadQueue)); handleResult(extractResult(&m_trkReadQueue, m_serialFrame));
m_trkWriteBusy = false; m_trkWriteBusy = false;
} }
@@ -1612,6 +1616,8 @@ static bool readAdapterArgs(const QStringList &args, AdapterOptions *o)
o->registerEndianness = BigEndian; o->registerEndianness = BigEndian;
} else if (*it == QLatin1String("-s")) { } else if (*it == QLatin1String("-s")) {
o->useSocket = true; o->useSocket = true;
} else if (*it == QLatin1String("-f")) {
o->serialFrame = false;
} }
} else { } else {
switch (argNumber++) { switch (argNumber++) {
@@ -1639,6 +1645,7 @@ int main(int argc, char *argv[])
if (!readAdapterArgs(app.arguments(), &options)) { if (!readAdapterArgs(app.arguments(), &options)) {
qDebug("Usage: %s [-v|-q] [-s][-l] <trk com/trkservername> <gdbserverport>\n" qDebug("Usage: %s [-v|-q] [-s][-l] <trk com/trkservername> <gdbserverport>\n"
"Options: -v verbose\n" "Options: -v verbose\n"
" -f Turn serial message frame off\n"
" -q quiet\n" " -q quiet\n"
" -s Use socket (simulation)\n" " -s Use socket (simulation)\n"
" -b Set register endianness to big\n", argv[0]); " -b Set register endianness to big\n", argv[0]);
@@ -1651,6 +1658,7 @@ int main(int argc, char *argv[])
adapter.setVerbose(options.verbose); adapter.setVerbose(options.verbose);
adapter.setRegisterEndianness(options.registerEndianness); adapter.setRegisterEndianness(options.registerEndianness);
adapter.setUseSocket(options.useSocket); adapter.setUseSocket(options.useSocket);
adapter.setSerialFrame(options.serialFrame);
if (adapter.startServer()) if (adapter.startServer())
return app.exec(); return app.exec();
return 4; return 4;

View File

@@ -42,6 +42,9 @@
#else #else
# include <stdio.h> # include <stdio.h>
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <termios.h>
# include <errno.h>
# include <string.h>
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -125,6 +128,7 @@ struct LauncherPrivate {
QString m_copySrcFileName; QString m_copySrcFileName;
QString m_copyDstFileName; QString m_copyDstFileName;
QString m_installFileName; QString m_installFileName;
bool m_serialFrame;
int m_verbose; int m_verbose;
}; };
@@ -135,6 +139,7 @@ LauncherPrivate::LauncherPrivate() :
m_trkWriteToken(0), m_trkWriteToken(0),
m_trkWriteBusy(false), m_trkWriteBusy(false),
m_timerId(-1), m_timerId(-1),
m_serialFrame(true),
m_verbose(0) m_verbose(0)
{ {
} }
@@ -173,6 +178,11 @@ void Launcher::setInstallFileName(const QString &name)
d->m_installFileName = name; d->m_installFileName = name;
} }
void Launcher::setSerialFrame(bool b)
{
d->m_serialFrame = b;
}
bool Launcher::startServer(QString *errorMessage) bool Launcher::startServer(QString *errorMessage)
{ {
if (d->m_verbose) { if (d->m_verbose) {
@@ -239,6 +249,27 @@ bool Launcher::openTrkPort(const QString &port, QString *errorMessage)
*errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->m_file.errorString()); *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->m_file.errorString());
return false; return false;
} }
struct termios termInfo;
if (tcgetattr(d->m_file.handle(), &termInfo) < 0) {
*errorMessage = QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
return false;
}
// Turn off terminal echo as not get messages back, among other things
termInfo.c_cflag|=CREAD|CLOCAL;
termInfo.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
termInfo.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
termInfo.c_oflag&=(~OPOST);
termInfo.c_cc[VMIN]=0;
termInfo.c_cc[VINTR] = _POSIX_VDISABLE;
termInfo.c_cc[VQUIT] = _POSIX_VDISABLE;
termInfo.c_cc[VSTART] = _POSIX_VDISABLE;
termInfo.c_cc[VSTOP] = _POSIX_VDISABLE;
termInfo.c_cc[VSUSP] = _POSIX_VDISABLE;
if (tcsetattr(d->m_file.handle(), TCSAFLUSH, &termInfo) < 0) {
*errorMessage = QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)));
return false;
}
return true; return true;
#endif #endif
} }
@@ -324,7 +355,7 @@ void Launcher::tryTrkWrite()
void Launcher::trkWrite(const TrkMessage &msg) void Launcher::trkWrite(const TrkMessage &msg)
{ {
QByteArray ba = frameMessage(msg.code, msg.token, msg.data); QByteArray ba = frameMessage(msg.code, msg.token, msg.data, d->m_serialFrame);
d->m_writtenTrkMessages.insert(msg.token, msg); d->m_writtenTrkMessages.insert(msg.token, msg);
d->m_trkWriteBusy = true; d->m_trkWriteBusy = true;
@@ -364,10 +395,11 @@ void Launcher::tryTrkRead()
while (TryReadFile(d->m_hdevice, buffer, BUFFERSIZE, &charsRead, NULL)) { while (TryReadFile(d->m_hdevice, buffer, BUFFERSIZE, &charsRead, NULL)) {
d->m_trkReadQueue.append(buffer, charsRead); d->m_trkReadQueue.append(buffer, charsRead);
if (isValidTrkResult(d->m_trkReadQueue)) if (isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame))
break; break;
} }
if (!isValidTrkResult(d->m_trkReadQueue)) { const ushort len = isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame);
if (!len) {
logMessage("Partial message: " + stringFromArray(d->m_trkReadQueue)); logMessage("Partial message: " + stringFromArray(d->m_trkReadQueue));
return; return;
} }
@@ -377,7 +409,8 @@ void Launcher::tryTrkRead()
return; return;
const QByteArray data = d->m_file.read(size); const QByteArray data = d->m_file.read(size);
d->m_trkReadQueue.append(data); d->m_trkReadQueue.append(data);
if (!isValidTrkResult(d->m_trkReadQueue)) { const ushort len = isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame);
if (!len) {
if (d->m_trkReadQueue.size() > 10) { if (d->m_trkReadQueue.size() > 10) {
logMessage(QString::fromLatin1("Unable to extract message from '%1' '%2'"). logMessage(QString::fromLatin1("Unable to extract message from '%1' '%2'").
arg(QLatin1String(d->m_trkReadQueue.toHex())).arg(QString::fromAscii(d->m_trkReadQueue))); arg(QLatin1String(d->m_trkReadQueue.toHex())).arg(QString::fromAscii(d->m_trkReadQueue)));
@@ -385,8 +418,8 @@ void Launcher::tryTrkRead()
return; return;
} }
#endif // Q_OS_WIN #endif // Q_OS_WIN
logMessage("READ: " + stringFromArray(d->m_trkReadQueue)); logMessage(QString::fromLatin1("READ: %1 bytes %2").arg(len).arg(stringFromArray(d->m_trkReadQueue)));
handleResult(extractResult(&d->m_trkReadQueue)); handleResult(extractResult(&d->m_trkReadQueue, d->m_serialFrame));
d->m_trkWriteBusy = false; d->m_trkWriteBusy = false;
} }

View File

@@ -51,7 +51,8 @@ public:
void setCopyFileName(const QString &srcName, const QString &dstName); void setCopyFileName(const QString &srcName, const QString &dstName);
void setInstallFileName(const QString &name); void setInstallFileName(const QString &name);
bool startServer(QString *errorMessage); bool startServer(QString *errorMessage);
void setVerbose(int v); void setVerbose(int v);
void setSerialFrame(bool b);
signals: signals:
void copyingStarted(); void copyingStarted();

View File

@@ -6,7 +6,8 @@
static const char *usageC = static const char *usageC =
"\nUsage: %1 <trk_port_name> [-v] [-i remote_sis_file | -I local_sis_file remote_sis_file] <remote_executable_name>\n" "\nUsage: %1 <trk_port_name> [-v] [-i remote_sis_file | -I local_sis_file remote_sis_file] <remote_executable_name>\n"
"\nOptions:\n -v verbose\n\n" "\nOptions:\n -v verbose\n"
" -f turn serial message frame off\n\n"
"\nPing:\n" "\nPing:\n"
"%1 COM5\n" "%1 COM5\n"
"\nRemote launch:\n" "\nRemote launch:\n"
@@ -40,6 +41,9 @@ static bool parseArguments(const QStringList &arguments, trk::Launcher &launcher
case 'v': case 'v':
verbosity++; verbosity++;
break; break;
case 'f':
launcher.setSerialFrame(false);
break;verbosity++;
case 'i': case 'i':
install = true; install = true;
break; break;

View File

@@ -52,9 +52,10 @@ void signalHandler(int)
using namespace trk; using namespace trk;
struct TrkOptions { struct TrkOptions {
TrkOptions() : verbose(1) {} TrkOptions() : verbose(1), serialFrame(true) {}
int verbose; int verbose;
bool serialFrame;
QString serverName; QString serverName;
QString dumpName; QString dumpName;
QStringList additionalDumps; QStringList additionalDumps;
@@ -191,6 +192,7 @@ public:
void setServerName(const QString &name) { m_serverName = name; } void setServerName(const QString &name) { m_serverName = name; }
void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; } void setMemoryDumpName(const QString &source) { m_memoryDumpName = source; }
void setVerbose(int v) { m_verbose = v; } void setVerbose(int v) { m_verbose = v; }
void setSerialFrame(bool b) { m_serialFrame = b; }
bool readDump(const QString &fn); bool readDump(const QString &fn);
bool startServer(); bool startServer();
@@ -218,12 +220,15 @@ private:
Inferior m_inferior; Inferior m_inferior;
byte m_notificationToken; byte m_notificationToken;
int m_verbose; int m_verbose;
bool m_serialFrame;
}; };
TrkServer::TrkServer() : m_verbose(1) TrkServer::TrkServer() :
m_adapterConnection(0),
m_notificationToken(0),
m_verbose(1),
m_serialFrame(true)
{ {
m_adapterConnection = 0;
m_notificationToken = 0;
} }
TrkServer::~TrkServer() TrkServer::~TrkServer()
@@ -294,12 +299,12 @@ void TrkServer::readFromAdapter()
logMessage("buffer: " + stringFromArray(m_adapterReadBuffer)); logMessage("buffer: " + stringFromArray(m_adapterReadBuffer));
while (!m_adapterReadBuffer.isEmpty()) while (!m_adapterReadBuffer.isEmpty())
handleAdapterMessage(extractResult(&m_adapterReadBuffer)); handleAdapterMessage(extractResult(&m_adapterReadBuffer, m_serialFrame));
} }
void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data) void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data)
{ {
QByteArray msg = frameMessage(command, token, data); QByteArray msg = frameMessage(command, token, data, m_serialFrame);
logMessage("trk: <- " + stringFromArray(msg)); logMessage("trk: <- " + stringFromArray(msg));
m_adapterConnection->write(msg); m_adapterConnection->write(msg);
} }
@@ -450,7 +455,10 @@ static bool readTrkArgs(const QStringList &args, TrkOptions *o)
o->verbose++; o->verbose++;
} else if (*it == QLatin1String("-q")) { } else if (*it == QLatin1String("-q")) {
o->verbose = 0; o->verbose = 0;
} else if (*it == QLatin1String("-f")) {
o->serialFrame= false;
} }
} else { } else {
switch (argNumber++) { switch (argNumber++) {
case 0: case 0:
@@ -479,6 +487,7 @@ int main(int argc, char *argv[])
if (!readTrkArgs(app.arguments(), &options)) { if (!readTrkArgs(app.arguments(), &options)) {
qWarning("Usage: %s [-v|-q] <trkservername> <replaysource> [additional dumps]\n" qWarning("Usage: %s [-v|-q] <trkservername> <replaysource> [additional dumps]\n"
"Options: -v verbose\n" "Options: -v verbose\n"
" -f Turn serial message frame off\n"
" -q quiet\n" " -q quiet\n"
" Additional dump names must follow the naming convention '0x4AD.bin", argv[0]); " Additional dump names must follow the naming convention '0x4AD.bin", argv[0]);
return 1; return 1;
@@ -487,6 +496,7 @@ int main(int argc, char *argv[])
TrkServer server; TrkServer server;
server.setServerName(options.serverName); server.setServerName(options.serverName);
server.setMemoryDumpName(options.dumpName); server.setMemoryDumpName(options.dumpName);
server.setSerialFrame(options.serialFrame);
foreach(const QString &ad, options.additionalDumps) foreach(const QString &ad, options.additionalDumps)
if (!server.readDump(ad)) if (!server.readDump(ad))
return -1; return -1;

View File

@@ -43,6 +43,13 @@ QByteArray hexNumber(uint n, int digits)
return QByteArray(digits - ba.size(), '0') + ba; return QByteArray(digits - ba.size(), '0') + ba;
} }
TrkResult::TrkResult() :
code(0),
token(0),
isDebugOutput(false)
{
}
QString TrkResult::toString() const QString TrkResult::toString() const
{ {
QString res = stringFromByte(code) + "[" + stringFromByte(token); QString res = stringFromByte(code) + "[" + stringFromByte(token);
@@ -50,7 +57,7 @@ QString TrkResult::toString() const
return res + "] " + stringFromArray(data); return res + "] " + stringFromArray(data);
} }
QByteArray frameMessage(byte command, byte token, const QByteArray &data) QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame)
{ {
byte s = command + token; byte s = command + token;
for (int i = 0; i != data.size(); ++i) for (int i = 0; i != data.size(); ++i)
@@ -66,13 +73,15 @@ QByteArray frameMessage(byte command, byte token, const QByteArray &data)
response.append(char(checksum)); response.append(char(checksum));
QByteArray encodedData = encode7d(response); QByteArray encodedData = encode7d(response);
ushort encodedSize = encodedData.size() + 2; // 2 x 0x7e
QByteArray ba; QByteArray ba;
ba.append(char(0x01)); if (serialFrame) {
ba.append(char(0x90)); ba.append(char(0x01));
ba.append(char(encodedSize / 256)); ba.append(char(0x90));
ba.append(char(encodedSize % 256)); const ushort encodedSize = encodedData.size() + 2; // 2 x 0x7e
ba.append(char(encodedSize / 256));
ba.append(char(encodedSize % 256));
}
ba.append(char(0x7e)); ba.append(char(0x7e));
ba.append(encodedData); ba.append(encodedData);
ba.append(char(0x7e)); ba.append(char(0x7e));
@@ -82,38 +91,48 @@ QByteArray frameMessage(byte command, byte token, const QByteArray &data)
/* returns 0 if array doesn't represent a result, /* returns 0 if array doesn't represent a result,
otherwise returns the length of the result data */ otherwise returns the length of the result data */
ushort isValidTrkResult(const QByteArray &buffer) ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame)
{ {
if (buffer.length() < 4) if (serialFrame) {
return 0; // Serial protocol with length info
if (buffer.at(0) != 0x01 || byte(buffer.at(1)) != 0x90) if (buffer.length() < 4)
return 0; return 0;
ushort len = extractShort(buffer.data() + 2); if (buffer.at(0) != 0x01 || byte(buffer.at(1)) != 0x90)
return 0;
if (buffer.size() < len + 4) { const ushort len = extractShort(buffer.data() + 2);
return 0; return (buffer.size() >= len + 4) ? len : ushort(0);
} }
return len; // Frameless protocol without length info
const char delimiter = char(0x7e);
const int firstDelimiterPos = buffer.indexOf(delimiter);
// Regular message delimited by 0x7e..0x7e
if (firstDelimiterPos == 0) {
const int endPos = buffer.indexOf(delimiter, firstDelimiterPos + 1);
return endPos != -1 ? endPos + 1 - firstDelimiterPos : 0;
}
// Some ASCII log message up to first delimiter or all
return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size();
} }
TrkResult extractResult(QByteArray *buffer) TrkResult extractResult(QByteArray *buffer, bool serialFrame)
{ {
TrkResult result; TrkResult result;
ushort len = isValidTrkResult(*buffer); const ushort len = isValidTrkResult(*buffer, serialFrame);
if (!len) if (!len)
return result; return result;
// handle receiving application output, which is not a regular command // handle receiving application output, which is not a regular command
if (buffer->at(4) != 0x7e) { const int delimiterPos = serialFrame ? 4 : 0;
if (buffer->at(delimiterPos) != 0x7e) {
result.isDebugOutput = true; result.isDebugOutput = true;
result.data = buffer->mid(4, len); result.data = buffer->mid(delimiterPos, len);
result.data.replace("\r\n", "\n"); result.data.replace("\r\n", "\n");
*buffer = buffer->mid(4 + len); *buffer->remove(0, delimiterPos + len);
return result; return result;
} }
// FIXME: what happens if the length contains 0xfe? // FIXME: what happens if the length contains 0xfe?
// Assume for now that it passes unencoded! // Assume for now that it passes unencoded!
QByteArray data = decode7d(buffer->mid(5, len - 2)); const QByteArray data = decode7d(buffer->mid(delimiterPos + 1, len - 2));
*buffer->remove(0, 4 + len); *buffer->remove(0, delimiterPos + len);
byte sum = 0; byte sum = 0;
for (int i = 0; i < data.size(); ++i) // 3 = 2 * 0xfe + sum for (int i = 0; i < data.size(); ++i) // 3 = 2 * 0xfe + sum

View File

@@ -171,7 +171,7 @@ struct Breakpoint
struct TrkResult struct TrkResult
{ {
TrkResult() { code = token = 0; isDebugOutput = false; } TrkResult();
QString toString() const; QString toString() const;
// 0 for no error. // 0 for no error.
int errorCode() const; int errorCode() const;
@@ -183,10 +183,11 @@ struct TrkResult
bool isDebugOutput; bool isDebugOutput;
}; };
// returns a QByteArray containing 0x01 0x90 <len> 0x7e encoded7d(ba) 0x7e // returns a QByteArray containing optionally
QByteArray frameMessage(byte command, byte token, const QByteArray &data); // the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e
ushort isValidTrkResult(const QByteArray &buffer); QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame);
TrkResult extractResult(QByteArray *buffer); ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame);
TrkResult extractResult(QByteArray *buffer, bool serialFrame);
QByteArray errorMessage(byte code); QByteArray errorMessage(byte code);
QByteArray hexNumber(uint n, int digits = 0); QByteArray hexNumber(uint n, int digits = 0);
uint swapEndian(uint in); uint swapEndian(uint in);