Skip to content

Commit 175e602

Browse files
committed
qt: Added support of async read/write from/to serial port and changed read chip ID to use async operations
1 parent 889053d commit 175e602

9 files changed

+338
-56
lines changed

qt/main_window.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
#include "main_window.h"
77
#include "ui_main_window.h"
8-
#include "programmer.h"
98
#include "chip_db.h"
109
#include <QDebug>
1110
#include <QFileDialog>
@@ -171,19 +170,19 @@ void MainWindow::slotProgConnect()
171170
}
172171
}
173172

174-
void MainWindow::slotProgReadDeviceId()
173+
void MainWindow::readChipIdCb(ChipId id)
175174
{
176-
ChipId id;
177175
QString idStr;
178176

179-
if (prog->readChipId(&id))
180-
log(tr("Failed to read chip ID\n"));
181-
else
182-
{
183-
idStr.sprintf("0x%02X 0x%02X 0x%02X 0x%02X", id.makerId, id.deviceId,
184-
id.thirdId, id.fourthId);
185-
ui->deviceValueLabel->setText(idStr);
186-
}
177+
idStr.sprintf("0x%02X 0x%02X 0x%02X 0x%02X", id.makerId, id.deviceId,
178+
id.thirdId, id.fourthId);
179+
ui->deviceValueLabel->setText(idStr);
180+
}
181+
182+
void MainWindow::slotProgReadDeviceId()
183+
{
184+
prog->readChipId(std::bind(&MainWindow::readChipIdCb, this,
185+
std::placeholders::_1));
187186
}
188187

189188
void MainWindow::slotProgErase()

qt/main_window.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
#ifndef MAIN_WINDOW_H
77
#define MAIN_WINDOW_H
88

9+
#include "programmer.h"
910
#include <QMainWindow>
1011

1112
namespace Ui {
1213
class MainWindow;
1314
}
1415

15-
class Programmer;
16-
1716
class MainWindow : public QMainWindow
1817
{
1918
Q_OBJECT
@@ -29,6 +28,7 @@ class MainWindow : public QMainWindow
2928

3029
void insertBufferRow(quint8 *readBuf, quint32 size, quint32 rowNum,
3130
quint32 address);
31+
void readChipIdCb(ChipId id);
3232

3333
public slots:
3434
void slotFileOpen();

qt/programmer.cpp

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
Programmer::Programmer(QObject *parent) : QObject(parent)
1717
{
18+
serialPortReader = new SerialPortReader(&serialPort, this);
19+
serialPortWriter = new SerialPortWriter(&serialPort, this);
1820
}
1921

2022
Programmer::~Programmer()
@@ -149,59 +151,59 @@ int Programmer::handleWrongResp(uint8_t code)
149151
return -1;
150152
}
151153

152-
int Programmer::handleRespChipId(RespId *respId, ChipId *id)
154+
void Programmer::readRespChipIdCb(int status)
153155
{
154-
qint64 ret;
156+
uint size;
157+
RespId *respId;
155158

156-
if (respId->header.info != sizeof(respId->nandId))
157-
{
158-
qCritical() << "Wrong chip ID responce length";
159-
return -1;
160-
}
159+
if (status == SerialPortReader::READ_ERROR)
160+
return;
161161

162-
serialPort.waitForReadyRead(1);
163-
ret = serialPort.read((char *)&respId->nandId, sizeof(respId->nandId));
164-
if (ret < 0)
162+
size = readData.size();
163+
if (size < sizeof(RespHeader))
165164
{
166-
qCritical() << "Failed to read response data: " << serialPort.error()
167-
<< serialPort.errorString();
168-
return -1;
165+
qCritical() << "Header size of chip ID response is wrong:" << size;
166+
return;
169167
}
170168

171-
if (ret != sizeof(respId->nandId))
169+
respId = (RespId *)readData.data();
170+
switch (respId->header.code)
172171
{
173-
qCritical() << "Failed to read responce data: data was partially "
174-
"received";
175-
return -1;
172+
case RESP_DATA:
173+
if (size < sizeof(RespId))
174+
{
175+
qCritical() << "Size of chip ID response is wrong:" << size;
176+
return;
177+
}
178+
readChipIdCb(respId->nandId);
179+
break;
180+
case RESP_STATUS:
181+
handleStatus(&respId->header);
182+
break;
183+
default:
184+
handleWrongResp(respId->header.code);
185+
break;
176186
}
187+
}
177188

178-
*id = respId->nandId;
179-
180-
return 0;
189+
void Programmer::sendCmdCb(int status)
190+
{
191+
if (status == SerialPortWriter::WRITE_ERROR)
192+
return;
181193
}
182194

183-
int Programmer::readChipId(ChipId *id)
195+
void Programmer::readChipId(std::function<void(ChipId)> callback)
184196
{
185-
RespId respId;
186197
Cmd cmd = { .code = CMD_NAND_READ_ID };
187198

188-
if (sendCmd(&cmd, sizeof(cmd)))
189-
return -1;
190-
191-
if (readRespHead(&respId.header))
192-
return -1;
199+
serialPortReader->read(std::bind(&Programmer::readRespChipIdCb, this,
200+
std::placeholders::_1), &readData);
193201

194-
switch (respId.header.code)
195-
{
196-
case RESP_DATA:
197-
return handleRespChipId(&respId, id);
198-
case RESP_STATUS:
199-
return handleStatus(&respId.header);
200-
default:
201-
return handleWrongResp(respId.header.code);
202-
}
203-
204-
return 0;
202+
readChipIdCb = callback;
203+
writeData.clear();
204+
writeData.append((const char *)&cmd, sizeof(cmd));
205+
serialPortWriter->write(std::bind(&Programmer::sendCmdCb,
206+
this, std::placeholders::_1), &writeData);
205207
}
206208

207209
int Programmer::eraseChip(uint32_t addr, uint32_t len)

qt/programmer.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88

99
#include <QObject>
1010
#include <QtSerialPort/QSerialPort>
11+
#include <QByteArray>
1112
#include <cstdint>
13+
#include <functional>
14+
#include "serial_port_writer.h"
15+
#include "serial_port_reader.h"
1216

1317
using namespace std;
1418

@@ -111,22 +115,28 @@ class Programmer : public QObject
111115
Q_OBJECT
112116

113117
QSerialPort serialPort;
114-
115118
bool isConn;
119+
std::function<void(ChipId)> readChipIdCb;
116120

117121
int sendCmd(Cmd *cmd, size_t size);
122+
void sendCmdCb(int status);
118123
int readRespHead(RespHeader *respHead);
119124
int readRespBadBlockAddress(RespBadBlock *badBlock);
125+
void readRespChipIdCb(int status);
120126
int handleStatus(RespHeader *respHead);
121127
int handleWrongResp(uint8_t code);
122-
int handleRespChipId(RespId *respId, ChipId *id);
123128
public:
129+
QByteArray readData;
130+
QByteArray writeData;
131+
SerialPortWriter *serialPortWriter;
132+
SerialPortReader *serialPortReader;
133+
124134
explicit Programmer(QObject *parent = 0);
125135
~Programmer();
126136
int connect();
127137
void disconnect();
128138
bool isConnected();
129-
int readChipId(ChipId *id);
139+
void readChipId(std::function<void(ChipId)> callback);
130140
int eraseChip(uint32_t addr, uint32_t len);
131141
int readChip(uint8_t *buf, uint32_t addr, uint32_t len);
132142
int writeChip(uint8_t *buf, uint32_t addr, uint32_t len);

qt/qt.pro

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ TEMPLATE = app
2020
SOURCES += main.cpp\
2121
main_window.cpp \
2222
programmer.cpp \
23-
chip_db.cpp
23+
chip_db.cpp \
24+
serial_port_writer.cpp \
25+
serial_port_reader.cpp
2426

2527
HEADERS += main_window.h \
2628
programmer.h \
27-
chip_db.h
29+
chip_db.h \
30+
serial_port_writer.h \
31+
serial_port_reader.h
2832

2933
FORMS += main_window.ui
3034

qt/serial_port_reader.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* Copyright (C) 2017 Bogdan Bogush <[email protected]>
2+
* This program is free software; you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License version 3.
4+
*/
5+
6+
#include "serial_port_reader.h"
7+
#include <QDebug>
8+
#include <QString>
9+
10+
#define READ_TIMEOUT_MS 100
11+
12+
SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent):
13+
QObject(parent), serialPort(serialPort)
14+
{
15+
timer.setSingleShot(true);
16+
}
17+
18+
void SerialPortReader::signalConnect()
19+
{
20+
connect(serialPort, SIGNAL(readyRead()), SLOT(handleReadyRead()));
21+
connect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)),
22+
SLOT(handleError(QSerialPort::SerialPortError)));
23+
connect(&timer, SIGNAL(timeout()), SLOT(handleTimeout()));
24+
}
25+
26+
void SerialPortReader::signalDisconnect()
27+
{
28+
disconnect(serialPort, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
29+
disconnect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this,
30+
SLOT(handleError(QSerialPort::SerialPortError)));
31+
disconnect(&timer, SIGNAL(timeout()), this, SLOT(handleTimeout()));
32+
}
33+
34+
void SerialPortReader::read(std::function<void(int)> callback,
35+
QByteArray *data)
36+
{
37+
signalConnect();
38+
readData = data;
39+
this->callback = callback;
40+
timer.start(READ_TIMEOUT_MS);
41+
}
42+
43+
void SerialPortReader::readEnd(int status)
44+
{
45+
callback(status);
46+
signalDisconnect();
47+
timer.stop();
48+
}
49+
50+
void SerialPortReader::handleReadyRead()
51+
{
52+
readData->append(serialPort->readAll());
53+
timer.start(READ_TIMEOUT_MS);
54+
}
55+
56+
void SerialPortReader::handleTimeout()
57+
{
58+
if (readData->isEmpty())
59+
{
60+
qCritical() << QString("Timeout to read data from port %1\n")
61+
.arg(serialPort->portName());
62+
readEnd(READ_ERROR);
63+
return;
64+
}
65+
66+
readEnd(READ_OK);
67+
}
68+
69+
void SerialPortReader::handleError(QSerialPort::SerialPortError /* error */)
70+
{
71+
qCritical() << QString("Failed to read data from port %1, error: %2\n")
72+
.arg(serialPort->portName()).arg(serialPort->errorString());
73+
74+
readEnd(READ_ERROR);
75+
}
76+

qt/serial_port_reader.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Copyright (C) 2017 Bogdan Bogush <[email protected]>
2+
* This program is free software; you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License version 3.
4+
*/
5+
6+
#ifndef SERIALPORTREADER_H
7+
#define SERIALPORTREADER_H
8+
9+
#include <QtSerialPort/QSerialPort>
10+
#include <QTimer>
11+
#include <QByteArray>
12+
#include <QObject>
13+
#include <functional>
14+
15+
class SerialPortReader: public QObject
16+
{
17+
Q_OBJECT
18+
19+
QSerialPort *serialPort;
20+
QByteArray *readData;
21+
QTimer timer;
22+
std::function<void(int)> callback;
23+
24+
void signalConnect();
25+
void signalDisconnect();
26+
void readEnd(int status);
27+
28+
public:
29+
enum
30+
{
31+
READ_ERROR = -1,
32+
READ_OK = 0
33+
};
34+
35+
explicit SerialPortReader(QSerialPort *serialPort,
36+
QObject *parent = 0);
37+
38+
void read(std::function<void(int)> callback, QByteArray *data);
39+
40+
public slots:
41+
void handleReadyRead();
42+
void handleTimeout();
43+
void handleError(QSerialPort::SerialPortError error);
44+
};
45+
46+
#endif // SERIALPORTREADER_H

0 commit comments

Comments
 (0)