From f36ba338f16fcf62165c38d529f35c14c5c28bd5 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Fri, 28 Aug 2015 11:31:15 -0400 Subject: [PATCH] Added a firmware uploader that can be used to upload firmware to supported cortex M3 boards (gvret, gevcu, evtvbms, etc) - Not tested to properly work yet but it does operate. Use at your own risk! --- SavvyCAN.pro | 9 +- firmwareuploaderwindow.cpp | 232 +++++++++++++++++++++++++++++++++++++ firmwareuploaderwindow.h | 53 +++++++++ firmwareuploaderwindow.ui | 106 +++++++++++++++++ mainwindow.cpp | 18 +++ mainwindow.h | 4 + mainwindow.ui | 8 +- serialworker.cpp | 8 +- serialworker.h | 3 + 9 files changed, 436 insertions(+), 5 deletions(-) create mode 100644 firmwareuploaderwindow.cpp create mode 100644 firmwareuploaderwindow.h create mode 100644 firmwareuploaderwindow.ui diff --git a/SavvyCAN.pro b/SavvyCAN.pro index 1a4ba41..5d9ddd3 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -34,7 +34,8 @@ SOURCES += main.cpp\ dbcsignaleditor.cpp \ framefileio.cpp \ filecomparatorwindow.cpp \ - mainsettingsdialog.cpp + mainsettingsdialog.cpp \ + firmwareuploaderwindow.cpp HEADERS += mainwindow.h \ can_structs.h \ @@ -57,7 +58,8 @@ HEADERS += mainwindow.h \ framefileio.h \ config.h \ filecomparatorwindow.h \ - mainsettingsdialog.h + mainsettingsdialog.h \ + firmwareuploaderwindow.h FORMS += mainwindow.ui \ graphingwindow.ui \ @@ -70,7 +72,8 @@ FORMS += mainwindow.ui \ dbcmaineditor.ui \ dbcsignaleditor.ui \ filecomparatorwindow.ui \ - mainsettingsdialog.ui + mainsettingsdialog.ui \ + firmwareuploaderwindow.ui DISTFILES += diff --git a/firmwareuploaderwindow.cpp b/firmwareuploaderwindow.cpp new file mode 100644 index 0000000..b9be616 --- /dev/null +++ b/firmwareuploaderwindow.cpp @@ -0,0 +1,232 @@ +#include "firmwareuploaderwindow.h" +#include "ui_firmwareuploaderwindow.h" +#include "mainwindow.h" + +#include + +FirmwareUploaderWindow::FirmwareUploaderWindow(const QVector *frames, QWidget *parent) : + QDialog(parent), + ui(new Ui::FirmwareUploaderWindow) +{ + ui->setupUi(this); + + transferInProgress = false; + startedProcess = false; + firmwareSize = 0; + currentSendingPosition = 0; + baseAddress = 0; + bus = 0; + modelFrames = frames; + + ui->lblFilename->setText(""); + ui->spinBus->setValue(0); + ui->spinBus->setMaximum(1); + ui->txtBaseAddr->setText("0x100"); + updateProgress(); + + timer = new QTimer(); + timer->setInterval(100); //100ms without a reply will cause us to attempt a resend + + connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int))); + connect(ui->btnLoadFile, SIGNAL(clicked(bool)), this, SLOT(handleLoadFile())); + connect(ui->btnStartStop, SIGNAL(clicked(bool)), this, SLOT(handleStartStopTransfer())); + connect(timer, SIGNAL(timeout()), this, SLOT(timerElapsed())); +} + +FirmwareUploaderWindow::~FirmwareUploaderWindow() +{ + timer->stop(); + delete timer; + delete ui; +} + +void FirmwareUploaderWindow::updateProgress() +{ + ui->lblProgress->setText(QString::number(currentSendingPosition * 4) + " of " + QString::number(firmwareSize) + " transferred"); +} + +void FirmwareUploaderWindow::updatedFrames(int numFrames) +{ + CANFrame thisFrame; + if (numFrames == -1) //all frames deleted. + { + } + else if (numFrames == -2) //all new set of frames. + { + } + else //just got some new frames. See if they are relevant. + { + /* + //run through the supposedly new frames in order + for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++) + { + thisFrame = modelFrames->at(i); + } + */ + } +} + +void FirmwareUploaderWindow::gotTargettedFrame(int frameLoc) +{ + const CANFrame &frame = modelFrames->at(frameLoc); + if (frame.ID == (baseAddress + 0x10)) { + qDebug() << "Start firmware reply"; + if ((frame.data[0] == 0xDE) && (frame.data[1] == 0xAF)) + { + if ((frame.data[2] == 0xDE) && (frame.data[3] == 0xED)) + { + if ((frame.data[4] == (token & 0xFF)) && (frame.data[5] == ((token >> 8) & 0xFF))) + { + if ((frame.data[6] == ((token >> 16) & 0xFF)) && (frame.data[7] == ((token >> 24) & 0xFF))) + { + qDebug() << "starting firmware process"; + MainWindow::getReference()->setTargettedID(baseAddress + 0x20); + transferInProgress = true; + sendFirmwareChunk(); + } + } + } + } + } + + if (frame.ID == (baseAddress + 0x20)) { + qDebug() << "Firmware reception success reply"; + int seq = frame.data[0] + (256 * frame.data[1]); + if (seq == currentSendingPosition) + { + currentSendingPosition++; + if (currentSendingPosition * 4 > firmwareSize || currentSendingPosition > 65535) + { + transferInProgress = false; + timer->stop(); + handleStartStopTransfer(); + ui->progressBar->setValue(100); + sendFirmwareEnding(); + } + else + { + ui->progressBar->setValue((400 * currentSendingPosition) / firmwareSize); + updateProgress(); + sendFirmwareChunk(); + } + } + } +} + +void FirmwareUploaderWindow::timerElapsed() +{ + sendFirmwareChunk(); //resend +} + +void FirmwareUploaderWindow::sendFirmwareChunk() +{ + CANFrame *output = new CANFrame; + int firmwareLocation = currentSendingPosition * 4; + int xorByte = 0; + output->extended = false; + output->len = 7; + output->ID = baseAddress + 0x16; + output->data[0] = currentSendingPosition & 0xFF; + output->data[1] = (currentSendingPosition >> 8) & 0xFF; + output->data[2] = firmwareData[firmwareLocation++]; + output->data[3] = firmwareData[firmwareLocation++]; + output->data[4] = firmwareData[firmwareLocation++]; + output->data[5] = firmwareData[firmwareLocation++]; + for (int i = 0; i < 6; i++) xorByte = xorByte ^ output->data[i]; + output->data[6] = xorByte; + sendCANFrame(output, bus); + timer->start(); +} + +void FirmwareUploaderWindow::sendFirmwareEnding() +{ + CANFrame *output = new CANFrame; + output->extended = false; + output->len = 4; + output->ID = baseAddress + 0x30; + output->data[0] = 0xC0; + output->data[1] = 0xDE; + output->data[2] = 0xFA; + output->data[3] = 0xDE; + sendCANFrame(output, bus); +} + +void FirmwareUploaderWindow::handleStartStopTransfer() +{ + startedProcess = !startedProcess; + + if (startedProcess) //start the process + { + ui->progressBar->setValue(0); + ui->btnStartStop->setText("Stop Upload"); + token = Utility::ParseStringToNum(ui->txtToken->text()); + bus = ui->spinBus->value(); + baseAddress = Utility::ParseStringToNum(ui->txtBaseAddr->text()); + qDebug() << "Base address: " + QString::number(baseAddress); + MainWindow::getReference()->setTargettedID(baseAddress + 0x10); + CANFrame *output = new CANFrame; + output->extended = false; + output->len = 8; + output->ID = baseAddress; + output->data[0] = 0xDE; + output->data[1] = 0xAD; + output->data[2] = 0xBE; + output->data[3] = 0xEF; + output->data[4] = token & 0xFF; + output->data[5] = (token >> 8) & 0xFF; + output->data[6] = (token >> 16) & 0xFF; + output->data[7] = (token >> 24) & 0xFF; + sendCANFrame(output, bus); + } + else //stop anything in process + { + ui->btnStartStop->setText("Start Upload"); + MainWindow::getReference()->setTargettedID(-1); + } +} + +void FirmwareUploaderWindow::handleLoadFile() +{ + QString filename; + QFileDialog dialog; + bool result = false; + + QStringList filters; + filters.append(QString(tr("Raw firmware binary (*.bin)"))); + + dialog.setFileMode(QFileDialog::ExistingFile); + dialog.setNameFilters(filters); + dialog.setViewMode(QFileDialog::Detail); + + if (dialog.exec() == QDialog::Accepted) + { + filename = dialog.selectedFiles()[0]; + + loadBinaryFile(filename); + } +} + +void FirmwareUploaderWindow::loadBinaryFile(QString filename) +{ + + if (transferInProgress) handleStartStopTransfer(); + + QFile *inFile = new QFile(filename); + + if (!inFile->open(QIODevice::ReadOnly)) + { + delete inFile; + return; + } + + firmwareData = inFile->readAll(); + + currentSendingPosition = 0; + firmwareSize = firmwareData.length(); + + updateProgress(); + + inFile->close(); + delete inFile; +} + diff --git a/firmwareuploaderwindow.h b/firmwareuploaderwindow.h new file mode 100644 index 0000000..5371c19 --- /dev/null +++ b/firmwareuploaderwindow.h @@ -0,0 +1,53 @@ +#ifndef FIRMWAREUPLOADERWINDOW_H +#define FIRMWAREUPLOADERWINDOW_H + +#include +#include +#include "can_structs.h" +#include "utility.h" +#include "serialworker.h" + +namespace Ui { +class FirmwareUploaderWindow; +} + +class FirmwareUploaderWindow : public QDialog +{ + Q_OBJECT + +public: + explicit FirmwareUploaderWindow(const QVector *frames, QWidget *parent = 0); + ~FirmwareUploaderWindow(); + +signals: + void sendCANFrame(const CANFrame *, int); + +public slots: + void gotTargettedFrame(int frameLoc); + +private slots: + void handleLoadFile(); + void handleStartStopTransfer(); + void updatedFrames(int); + void timerElapsed(); + +private: + void updateProgress(); + void loadBinaryFile(QString); + void sendFirmwareChunk(); + void sendFirmwareEnding(); + + Ui::FirmwareUploaderWindow *ui; + bool transferInProgress; + bool startedProcess; + int firmwareSize; + int currentSendingPosition; + int baseAddress; + int bus; + uint32_t token; + QByteArray firmwareData; + const QVector *modelFrames; + QTimer *timer; +}; + +#endif // FIRMWAREUPLOADERWINDOW_H diff --git a/firmwareuploaderwindow.ui b/firmwareuploaderwindow.ui new file mode 100644 index 0000000..c49903a --- /dev/null +++ b/firmwareuploaderwindow.ui @@ -0,0 +1,106 @@ + + + FirmwareUploaderWindow + + + + 0 + 0 + 327 + 357 + + + + Dialog + + + + + + Loaded File: + + + + + + + + + + + + + + Load File + + + + + + + Device Token: + + + + + + + + + + CAN Bus: + + + + + + + + + + Base Address: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + + + + + X of Y bytes + + + + + + + Start Upload + + + + + + + + diff --git a/mainwindow.cpp b/mainwindow.cpp index fe17f50..36f3b6b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -104,6 +104,7 @@ MainWindow::MainWindow(QWidget *parent) : dbcMainEditor = NULL; comparatorWindow = NULL; settingsDialog = NULL; + firmwareUploaderWindow = NULL; dbcHandler = new DBCHandler; bDirty = false; inhibitFilterUpdate = false; @@ -143,6 +144,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->listFilters, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(filterListItemChanged(QListWidgetItem*))); connect(ui->btnFilterAll, SIGNAL(clicked(bool)), this, SLOT(filterSetAll())); connect(ui->btnFilterNone, SIGNAL(clicked(bool)), this, SLOT(filterClearAll())); + connect(ui->actionFirmware_Uploader, SIGNAL(triggered(bool)), this, SLOT(showFirmwareUploaderWindow())); lbStatusConnected.setText(tr("Not connected")); updateFileStatus(); @@ -906,6 +908,11 @@ void MainWindow::gotDeviceInfo(int build, int swCAN) } } +void MainWindow::setTargettedID(int id) +{ + worker->targetFrameID(id); +} + void MainWindow::showSettingsDialog() { if (!settingsDialog) @@ -972,6 +979,17 @@ void MainWindow::showPlaybackWindow() playbackWindow->show(); } +void MainWindow::showFirmwareUploaderWindow() +{ + if (!firmwareUploaderWindow) + { + firmwareUploaderWindow = new FirmwareUploaderWindow(model->getListReference()); + connect(firmwareUploaderWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), worker, SLOT(sendFrame(const CANFrame*,int))); + connect(worker, SIGNAL(gotTargettedFrame(int)), firmwareUploaderWindow, SLOT(gotTargettedFrame(int))); + } + firmwareUploaderWindow->show(); +} + void MainWindow::showComparisonWindow() { if (!comparatorWindow) diff --git a/mainwindow.h b/mainwindow.h index 6d7ea61..a179cfc 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -17,6 +17,7 @@ #include "dbchandler.h" #include "dbcmaineditor.h" #include "mainsettingsdialog.h" +#include "firmwareuploaderwindow.h" namespace Ui { class MainWindow; @@ -30,6 +31,7 @@ public: explicit MainWindow(QWidget *parent = 0); static QString loadedFileName; static MainWindow *getReference(); + void setTargettedID(int); ~MainWindow(); private slots: @@ -52,6 +54,7 @@ private slots: void showFuzzyScopeWindow(); void showComparisonWindow(); void showSettingsDialog(); + void showFirmwareUploaderWindow(); void exitApp(); void handleSaveDecoded(); void changeBaudRates(); @@ -115,6 +118,7 @@ private: DBCMainEditor *dbcMainEditor; FileComparatorWindow *comparatorWindow; MainSettingsDialog *settingsDialog; + FirmwareUploaderWindow *firmwareUploaderWindow; //various private storage QLabel lbStatusConnected; diff --git a/mainwindow.ui b/mainwindow.ui index 51da1ee..57cbb8e 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -293,7 +293,7 @@ 0 0 800 - 26 + 21 @@ -314,6 +314,7 @@ + @@ -440,6 +441,11 @@ Save Filter Definition + + + Firmware Uploader + + diff --git a/serialworker.cpp b/serialworker.cpp index 1a004c1..18bc1a9 100644 --- a/serialworker.cpp +++ b/serialworker.cpp @@ -19,6 +19,7 @@ SerialWorker::SerialWorker(CANFrameModel *model, QObject *parent) : QObject(pare capturing = true; gotValidated = true; isAutoRestart = false; + targetID = -1; readSettings(); } @@ -245,7 +246,7 @@ void SerialWorker::procRXChar(unsigned char c) break; case 9: gotValidated = true; - qDebug() << "Got validated"; + //qDebug() << "Got validated"; rx_state = IDLE; break; } @@ -302,6 +303,7 @@ void SerialWorker::procRXChar(unsigned char c) { canModel->addFrame(*buildFrame, false); gotFrames++; + if (buildFrame->ID == targetID) emit gotTargettedFrame(canModel->rowCount() - 1); } } break; @@ -477,3 +479,7 @@ void SerialWorker::startFrameCapture() capturing = true; } +void SerialWorker::targetFrameID(int target) +{ + targetID = target; +} diff --git a/serialworker.h b/serialworker.h index 0b3c3b7..116d334 100644 --- a/serialworker.h +++ b/serialworker.h @@ -32,6 +32,7 @@ public: SerialWorker(CANFrameModel *model, QObject *parent = 0); ~SerialWorker(); void readSettings(); + void targetFrameID(int); signals: //we emit signals void error(const QString &); @@ -39,6 +40,7 @@ signals: //we emit signals void connectionSuccess(int, int); void connectionFailure(); void deviceInfo(int, int); + void gotTargettedFrame(int); private slots: //we receive things in slots void readSerialData(); @@ -70,6 +72,7 @@ private: QTime *elapsedTime; int framesPerSec; int gotFrames; + int targetID; STATE rx_state; int rx_step; CANFrame *buildFrame;