Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions flasher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,8 @@ FlashingInfo Flasher::CheckSignature()
bool Flasher::CheckAck()
{
bool success = false;
const auto data = serial_port_.readAll();
QByteArray data;
serial_port_.ReadData(data);
if (data.size() >= 2) {
if (0 == QString::compare("OK", data, Qt::CaseInsensitive)) {
qInfo() << "ACK";
Expand All @@ -563,7 +564,8 @@ bool Flasher::CheckTrue()
{
//TODO: better handling needed. For error false is returned
bool success = false;
const auto data = serial_port_.readAll();
QByteArray data;
serial_port_.ReadData(data);

if (0 == QString::compare("TRUE", data, Qt::CaseInsensitive)) {
qInfo() << "TRUE";
Expand Down Expand Up @@ -699,8 +701,10 @@ FlashingInfo Flasher::Erase()
void Flasher::GetVersion()
{
serial_port_.write(kVersionCmd, sizeof(kVersionCmd));
serial_port_.waitForReadyRead(kSerialTimeoutInMs);
emit ShowTextInBrowser(serial_port_.readAll());
serial_port_.WaitForReadyRead(kSerialTimeoutInMs);
QByteArray data;
serial_port_.ReadData(data);
emit ShowTextInBrowser(data);
}

bool Flasher::GetVersionJson(QJsonObject& out_json_object)
Expand Down Expand Up @@ -734,7 +738,7 @@ bool Flasher::IsFirmwareProtected()
{
qInfo() << "Send is firmware protected command";
serial_port_.write(kIsFwProtectedCmd, sizeof(kIsFwProtectedCmd));
serial_port_.waitForReadyRead(kSerialTimeoutInMs);
serial_port_.WaitForReadyRead(kSerialTimeoutInMs);
return CheckTrue();
}

Expand Down Expand Up @@ -795,7 +799,7 @@ FlashingInfo Flasher::SendFileSize()
bool Flasher::SendMessage(const char *data, qint64 length, int timeout_ms)
{
serial_port_.write(data, length);
serial_port_.waitForReadyRead(timeout_ms);
serial_port_.WaitForReadyRead(timeout_ms);
return CheckAck();
}

Expand Down Expand Up @@ -823,26 +827,22 @@ bool Flasher::ReadMessageWithCrc(const char *in_data, qint64 length, int timeout
serial_port_.write(in_data, length);

QByteArray data;
while (!timer.hasExpired(timeout_ms)) {

serial_port_.waitForReadyRead(kSerialTimeoutInMs);
data.append(serial_port_.readAll());
QByteArray data_crc = data.right(kCrc32Size);
serial_port_.WaitForReadyRead(timeout_ms);
serial_port_.ReadData(data);
QByteArray data_crc = data.right(kCrc32Size);

if (data.size() > kCrc32Size) {
if (data.size() > kCrc32Size) {

uint32_t out_data_size = data.size() - kCrc32Size;
uint32_t crc = Deserialize32(reinterpret_cast<uint8_t *>(data_crc.data()));
uint32_t calc_crc = crc::CalculateCrc32(reinterpret_cast<uint8_t *>(data.data()), out_data_size, false, false);
uint32_t out_data_size = data.size() - kCrc32Size;
uint32_t crc = Deserialize32(reinterpret_cast<uint8_t *>(data_crc.data()));
uint32_t calc_crc = crc::CalculateCrc32(reinterpret_cast<uint8_t *>(data.data()), out_data_size, false, false);

if (calc_crc == crc) {
out_data = data.left(out_data_size);
success = true;
break;
}
if (calc_crc == crc) {
out_data = data.left(out_data_size);
success = true;
}
}

}

return success;
Expand All @@ -858,7 +858,7 @@ void Flasher::SendFlashCommand()
{
qInfo() << "Send flash command";
serial_port_.write(kFlashFwCmd, sizeof(kFlashFwCmd));
serial_port_.waitForReadyRead(kSerialTimeoutInMs);
serial_port_.WaitForReadyRead(kSerialTimeoutInMs);
// Check ack
}

Expand Down
46 changes: 43 additions & 3 deletions serial_port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,58 @@
#include <QDebug>
#include <QElapsedTimer>
#include <QSerialPortInfo>
#include <QThread>

namespace communication {
namespace {

constexpr int kMaxNoDataPeriod {10}; //!< Max time in [ms] while waiting for new serial data. 10 ms = 1 kHz for sender minimal task frequency.
constexpr int kSerialTimeoutInMs {100};
constexpr char kSoftwareTypeCmd[] = "software_type";
constexpr char kSwTypeImBoot[] = "IMBootloader";
constexpr char kSwTypeImApp[] = "IMApplication";

} // namespace

SerialPort::SerialPort() = default;
SerialPort::SerialPort()
{
connect(this, &communication::SerialPort::readyRead, this, &communication::SerialPort::ReadyRead);
}
SerialPort::~SerialPort() = default;

void SerialPort::ReadyRead()
{
serial_rx_data_.append(readAll());
}

void SerialPort::ReadData(QByteArray& data_out)
{
data_out = serial_rx_data_;
serial_rx_data_.clear();
previous_rx_data_size_ = 0;
}

void SerialPort::WaitForReadyRead(int timeout)
{
QElapsedTimer timer;
timer.start();

while (!timer.hasExpired(timeout)) {

QObject().thread()->msleep(kMaxNoDataPeriod); // Give some time to the sender to send the data
waitForReadyRead(1); //QSerial known workaround for triggering readyRead signal(https://bugreports.qt.io/browse/QTBUG-78086)

int current_rx_data_size = serial_rx_data_.size();
if ((current_rx_data_size == previous_rx_data_size_) && (current_rx_data_size != 0)) {
// No new data. Ready to read, exit the loop.
break;
}

previous_rx_data_size_ = current_rx_data_size;
}
}


void SerialPort::CloseConn()
{
if (isOpen()) {
Expand All @@ -62,9 +100,11 @@ bool SerialPort::DetectBoard(bool& is_bootloader)
{
bool is_board_detected;
write(kSoftwareTypeCmd, sizeof(kSoftwareTypeCmd));
waitForReadyRead(kSerialTimeoutInMs);
QString software_type = readAll();
WaitForReadyRead(kSerialTimeoutInMs);
QByteArray data_out;
ReadData(data_out);

QString software_type = data_out;
if (software_type == kSwTypeImApp) {
is_bootloader = false;
is_board_detected = true;
Expand Down
21 changes: 21 additions & 0 deletions serial_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,30 @@ class SerialPort : public QSerialPort
void CloseConn();
bool TryOpenPort(bool& is_bootloader);

/**
* Wait until RX data is ready. The function has a predefined wait value with no data on the serial line,
* so it is able to receive data in chunks.
*
* @param[in] timeout Function timeout value
*/
void WaitForReadyRead(int timeout);

/**
* Function for copying data to a given reference. After data is copied internal buffer will be cleared.
*
* @param[out] data_out Reference to where data will be copied
*/
void ReadData(QByteArray& data_out);

public slots:
void ReadyRead();

private:
bool DetectBoard(bool& is_bootloader);
bool OpenConnection(const QString& port_name);

QByteArray serial_rx_data_; //!< Byte Array work as an RX buffer.
int previous_rx_data_size_{0};
};

} // namespace communication
Expand Down