From 002d58ba7b4f0dc3a58ad67a45bca44acb7ace6e Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Wed, 5 Apr 2023 14:18:29 +0200 Subject: [PATCH] Added dc_updateDC plus associated helper functions. dc_open_Serial: check if serial line is really open dc_close_Serial: check if serial line is really closed dc_isPortOpen: check if port is open directly on serial-object bl_checkBL: try to check if bootloader is running --- src/hwapi.cpp | 292 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 282 insertions(+), 10 deletions(-) diff --git a/src/hwapi.cpp b/src/hwapi.cpp index 6c19092..71fc7cb 100644 --- a/src/hwapi.cpp +++ b/src/hwapi.cpp @@ -8,6 +8,8 @@ */ #include +#include +#include #include "tslib.h" #include "hwapi.h" @@ -20,6 +22,10 @@ #include <../plugins/interfaces.h> +static const QMap baudrateMap = { + {"1200" , 0}, {"9600" , 1}, {"19200" , 2}, {"38400" , 3}, + {"57600" , 4}, {"115200" , 5} +}; hwapi::hwapi(QWidget *parent) : QObject(parent) { @@ -29,7 +35,6 @@ hwapi::hwapi(QWidget *parent) : QObject(parent) sendWRcmd_INI(); myDatif = new T_datif(); - } @@ -105,25 +110,49 @@ void hwapi::sub_storeSendingText(QByteArray *buf) const // start automatic READ requests // ------------------------------------------------------------------------------ -void hwapi::dc_openSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect) const -{ +bool hwapi::dc_openSerial(int BaudNr, QString BaudStr, + QString ComName, uint8_t connect) const { // BaudNr: 0:1200 1:9600 2:19200 3:38400 4:57600 5:115200 // BaudStr: for exapmle "19200" // ComName: for example "COM48" // connect: 0, 1 -//qDebug() << "~~>LIB" << "dc_openSerial called... " ; + //qDebug() << "~~>LIB" << "dc_openSerial called... " ; + epi_setSerial(BaudNr, BaudStr, ComName, connect); + // Actions: open serial port with parameters + for (int i = 0; i < 10; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (dc_isPortOpen()) { + return true; + } + } + return false; } -void hwapi::dc_closeSerial(void) const -{ +bool hwapi::dc_closeSerial(void) const { epi_closeSerial(); + for (int i = 0; i < 10; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (!dc_isPortOpen()) { + return true; + } + } + return false; } -bool hwapi::dc_isPortOpen(void) const -{ - return epi_isSerialPortOpen(); +bool hwapi::dc_isPortOpen(void) const { + if (myDatif) { + T_prot* prot = myDatif->getProt(); + if (prot) { + T_com *com = prot->getSerialPort(); + if (com) { + return com->isPortOpen(); + } + } + } + return false; + //return epi_isSerialPortOpen(); } void hwapi::dc_autoRequest(bool on) const @@ -135,6 +164,247 @@ void hwapi::dc_autoRequest(bool on) const epi_startEmmision(0); } +/******************************************************************************/ +// +// LEVEL 2: Help-functions for hwapi::dc_updateDC. +// +/******************************************************************************/ +hwapi::DownloadResult hwapi::sendStatus(int ret) const { + switch (ret) { // return values of dc are: + case 0: // 0: no answer by now + return DownloadResult::NOP; // 1: error + case 10: // 10: success + return DownloadResult::OK; + default:; + } + return DownloadResult::ERROR; +} + +hwapi::DownloadResult hwapi::sendNextAddress(int bNum) const { + // sends address only if blockNumber is one of 0, 1024, 2048, 3072, 4096 + int noAnswerCount = 0; + int errorCount = 0; + if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) { + qDebug() << "addr-block" << bNum << "..."; + while (noAnswerCount <= 250) { + bl_sendAddress(bNum); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + DownloadResult const res = sendStatus(bl_wasSendingAddOK()); + if (res != DownloadResult::NOP) { + if (res == DownloadResult::ERROR) { + if (++errorCount >= 10) { + qCritical() << "addr-block" << bNum << "...FAILED"; + return res; + } + } else { // res == DownloadResult::OK + qInfo() << "addr-block" << bNum << "...OK"; + return res; + } + } else { + noAnswerCount += 1; // no answer by now + } + } + // wait max. about 3 seconds + return DownloadResult::TIMEOUT; + } + // blockNumber is not one of 0, 1024, 2048, 3072, 4096 -> do nothing + return DownloadResult::NOP; +} + +hwinf::DownloadResult hwapi::sendNextDataBlock(QByteArray const &binary, + int bNum) const { + uint8_t local[66]; + int const bAddr = bNum * 64; + int noAnswerCount = 0; + int errorCount = 0; + + memcpy(local, binary.constData() + bAddr, 64); + local[64] = local[65] = 0x00; + + qDebug() << "data for addr" << bAddr << "..."; + + while (noAnswerCount <= 250) { + bl_sendDataBlock(64, local); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + DownloadResult const res = sendStatus(bl_wasSendingDataOK()); + if (res != DownloadResult::NOP) { + if (res == DownloadResult::ERROR) { + if (++errorCount >= 10) { + qCritical() << "data for addr" << bAddr << "...FAILED"; + return res; + } + } else { + qInfo() << "data for addr" << bAddr << "...OK"; + return res; + } + } else { + noAnswerCount += 1; // no answer by now + } + } + // wait max. about 3 seconds + return DownloadResult::TIMEOUT; +} + +hwinf::DownloadResult hwapi::dc_downloadBinary(QByteArray const &b) const { + + int const nBlocks = (((b.size())%64)==0) ? (b.size()/64) : (b.size()/64)+1; + + qInfo() << "total number of bytes to send to dc" << b.size(); + qInfo() << "total number of blocks to send to dc" << nBlocks; + + for (int blockNumber = 0; blockNumber < nBlocks; ++blockNumber) { + DownloadResult res = sendNextAddress(blockNumber); + if (res == DownloadResult::NOP) { // no address had to be + res = sendNextDataBlock(b, blockNumber); // sent, so send next block + } // as data block + if (res != DownloadResult::OK) { + return res; + } + } + + bl_sendLastBlock(); + return DownloadResult::OK; +} + +bool hwapi::startBootloader() const { + qDebug() << "starting bootloader..."; + int nTry = 5; + while (--nTry >= 0) { + bl_startBL(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (bl_isUp()) { + qInfo() << "starting bootloader...OK"; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + return true; + } + } + qCritical() << "starting bootloader...FAILED"; + return false; +} + +bool hwapi::stopBootloader() const { + qDebug() << "stopping bootloader..."; + int nTry = 5; + while (--nTry >= 0) { + bl_stopBL(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + if (!bl_isUp()) { + qInfo() << "stopping bootloader...OK"; + return true; + } + } + qCritical() << "stopping bootloader...FAILED"; + return false; +} + +// br is a index into a table, used for historical reasons. +bool hwapi::openSerial(int br, QString baudrate, QString comPort) const { + qDebug() << "opening serial" << br << baudrate << comPort << "..."; + if (dc_openSerial(br, baudrate, comPort, 1)) { // 1 for connect + qInfo() << "opening serial" << br << baudrate << comPort << "...OK"; + return true; + } + qCritical() << "opening serial" << br << baudrate << comPort << "...FAILED"; + return false; +} + +bool hwapi::closeSerial(QString comPort) const { + qDebug() << "closing serial" << comPort << "..."; + if (dc_closeSerial()) { + qInfo() << "closing serial" << comPort << "...OK"; + return true; + } else { + qCritical() << "closing serial" << comPort << "...FAILED"; + } + return false; +} + +bool hwapi::resetDeviceController() const { + qDebug() << "resetting device controller..."; + if (stopBootloader()) { // first stop a (maybe) running bootloader + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + dc_OrderToReset(); + // wait maximally 3 seconds, before starting bootloader + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + qInfo() << "resetting device controller...OK"; + return true; + } + return false; +} + +QByteArray hwapi::loadBinaryDCFile(QString filename) const { + qDebug() << "loading dc binary" << filename << "..."; + + QFile file(filename); // closed in destructor call + if (!file.exists()) { + qCritical() << file.fileName() << "does not exist"; + return QByteArray(); + } + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "cannot open file" << file.fileName(); + return QByteArray(); + } + qInfo() << "loading dc binary" << filename << "...OK"; + return file.readAll(); +} + +bool hwapi::downloadBinaryToDC(QString const &bFile) const { + qDebug() << "sending" << bFile << "to dc..."; + QByteArray const dcBinary = loadBinaryDCFile(bFile); + if (dcBinary.size() > 0) { + if (dc_downloadBinary(dcBinary) != DownloadResult::OK) { + qCritical() << "sending" << bFile << "to dc...FAILED"; + return false; + } else { + qInfo() << "sending" << bFile << "to dc...OK"; + } + } else { + qCritical() << "sending" << bFile << "to dc...FAILED"; + qCritical() << "loading binary" << bFile << "FAILED"; + return false; + } + return true; +} + +/******************************************************************************/ +// +// LEVEL 3: hwapi::dc_updateDC. +// +/******************************************************************************/ +bool hwapi::dc_updateDC(QString bFile, QString br, QString serial) const { + if (!baudrateMap.contains(br)) { // sanity check + qCritical() << "passed wrong baudrate" << br; + return false; + } + + qDebug() << "updating dc: " << bFile << br << serial << "..."; + + if (!openSerial(baudrateMap.value(br), br, serial)) { + return false; + } + if (!resetDeviceController()) { + closeSerial(serial); + return false; + } + if (!startBootloader()) { + closeSerial(serial); + return false; + } + if (!downloadBinaryToDC(bFile)) { + stopBootloader(); + closeSerial(serial); + qCritical() << "updating dc: " << bFile << br << serial << "...FAILED"; + return false; + } + + qInfo() << "updating dc: " << bFile << br << serial << "...OK"; + + stopBootloader(); + closeSerial(serial); + return true; +} + + // ------------------------------------------------------------------------------ // Level 1, control device-controller (functions of µC) // check serial connection to deviceController @@ -2577,13 +2847,15 @@ void hwapi::bl_startBL(void) const sendWRcmd_setSendBlock160(len, buf); } -void hwapi::bl_checkBL(void) const +bool hwapi::bl_checkBL(void) const { uint8_t len, buf[20]; //len=dcBL_readBLversion(buf); len=dcBL_readFWversion(buf); sendWRcmd_setSendBlock160(len, buf); + + return (len > 0); } bool hwapi::bl_isUp(void) const