Added verify-after-write capability

In order to do this, I changed the Programmer class to no longer take a
filename, but a QIODevice. It should have been done that way originally.

I also rearranged code so that I close the serial port BEFORE sending out
any signals. This was causing a problem if I tried doing something in a
slot connected to one of those signals.

I also fixed a few places where I was forgetting to close the serial
port.
This commit is contained in:
Doug Brown 2012-05-20 11:14:36 -07:00
parent b8bf3e878b
commit cec709c840
5 changed files with 351 additions and 51 deletions

View File

@ -32,6 +32,11 @@ MainWindow::MainWindow(QWidget *parent) :
ui->statusLabel->setText("");
ui->cancelButton->setEnabled(false);
readFile = NULL;
writeFile = NULL;
verifyArray = NULL;
verifyBuffer = NULL;
connect(p, SIGNAL(writeStatusChanged(WriteStatus)), SLOT(programmerWriteStatusChanged(WriteStatus)));
connect(p, SIGNAL(writeTotalLengthChanged(uint32_t)), SLOT(programmerWriteTotalLengthChanged(uint32_t)));
connect(p, SIGNAL(writeCompletionLengthChanged(uint32_t)), SLOT(programmerWriteCompletionLengthChanged(uint32_t)));
@ -109,16 +114,58 @@ void MainWindow::on_selectReadFileButton_clicked()
void MainWindow::on_readFromSIMMButton_clicked()
{
resetAndShowStatusPage();
p->readSIMMToFile(ui->chosenReadFile->text());
qDebug() << "Reading from SIMM...";
// We are not doing a verify after a write..
readVerifying = false;
if (readFile)
{
readFile->close();
delete readFile;
}
readFile = new QFile(ui->chosenReadFile->text());
if (readFile)
{
if (!readFile->open(QFile::WriteOnly))
{
delete readFile;
readFile = NULL;
programmerReadStatusChanged(ReadError);
return;
}
resetAndShowStatusPage();
p->readSIMM(readFile);
qDebug() << "Reading from SIMM...";
}
else
{
programmerReadStatusChanged(ReadError);
}
}
void MainWindow::on_writeToSIMMButton_clicked()
{
resetAndShowStatusPage();
p->writeFileToSIMM(ui->chosenWriteFile->text());
qDebug() << "Writing to SIMM...";
if (writeFile)
{
writeFile->close();
delete writeFile;
}
writeFile = new QFile(ui->chosenWriteFile->text());
if (writeFile)
{
if (!writeFile->open(QFile::ReadOnly))
{
delete writeFile;
writeFile = NULL;
programmerWriteStatusChanged(WriteError);
return;
}
resetAndShowStatusPage();
p->writeToSIMM(writeFile);
qDebug() << "Writing to SIMM...";
}
else
{
programmerWriteStatusChanged(WriteError);
}
}
void MainWindow::on_chosenWriteFile_textEdited(const QString &newText)
@ -144,14 +191,61 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
ui->statusLabel->setText("Erasing SIMM (this may take a few seconds)...");
break;
case WriteComplete:
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::information(this, "Write complete", "The write operation finished.");
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
if (ui->verifyAfterWriteBox->isChecked())
{
// Set up the read buffers
readVerifying = true;
if (verifyArray) delete verifyArray;
verifyArray = new QByteArray((int)p->SIMMCapacity(), 0);
if (verifyBuffer) delete verifyBuffer;
verifyBuffer = new QBuffer(verifyArray);
if (!verifyBuffer->open(QBuffer::ReadWrite))
{
delete verifyBuffer;
delete verifyArray;
verifyBuffer = NULL;
verifyArray = NULL;
programmerReadStatusChanged(ReadError);
return;
}
// Start reading from SIMM to temporary RAM buffer
resetAndShowStatusPage();
p->readSIMM(verifyBuffer);
qDebug() << "Reading from SIMM for verification...";
}
else
{
QMessageBox::information(this, "Write complete", "The write operation finished.");
ui->pages->setCurrentWidget(ui->controlPage);
}
break;
case WriteError:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Write error", "An error occurred writing to the SIMM.");
break;
case WriteCancelled:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Write cancelled", "The write operation was cancelled.");
break;
@ -159,14 +253,35 @@ void MainWindow::programmerWriteStatusChanged(WriteStatus newStatus)
ui->statusLabel->setText("Writing SIMM...");
break;
case WriteEraseFailed:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Write error", "An error occurred erasing the SIMM.");
break;
case WriteTimedOut:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Write timed out", "The write operation timed out.");
break;
case WriteFileTooBig:
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "File too big", "The file you chose to write to the SIMM is too big according to the chip size you have selected.");
break;
@ -237,23 +352,160 @@ void MainWindow::programmerReadStatusChanged(ReadStatus newStatus)
switch (newStatus)
{
case ReadStarting:
ui->statusLabel->setText("Reading SIMM contents...");
if (readVerifying)
{
ui->statusLabel->setText("Verifying SIMM contents...");
}
else
{
ui->statusLabel->setText("Reading SIMM contents...");
}
break;
case ReadComplete:
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::information(this, "Read complete", "The read operation finished.");
if (readVerifying)
{
// Re-open the write file temporarily to compare it against the buffer.
QFile temp(ui->chosenWriteFile->text());
if (!temp.open(QFile::ReadOnly))
{
QMessageBox::warning(this, "Verify failed", "Unable to open file for verification.");
}
else
{
QByteArray fileBytes = temp.readAll();
if (fileBytes.count() <= verifyArray->count())
{
const char *fileBytesPtr = fileBytes.constData();
const char *readBytesPtr = verifyArray->constData();
if (memcmp(fileBytesPtr, readBytesPtr, fileBytes.count()) != 0)
{
QMessageBox::warning(this, "Verify error", "The data read back from the SIMM did not match the data written to it.");
}
else
{
QMessageBox::information(this, "Write complete", "The write operation finished, and the contents were verified successfully.");
}
}
else
{
QMessageBox::warning(this, "Verify error", "The data read back from the SIMM did not match the data written to it.");
}
}
// Close stuff not needed anymore
if (verifyBuffer)
{
verifyBuffer->close();
delete verifyBuffer;
verifyBuffer = NULL;
}
if (verifyArray)
{
delete verifyArray;
verifyArray = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
}
else
{
if (readFile)
{
readFile->close();
delete readFile;
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::information(this, "Read complete", "The read operation finished.");
}
break;
case ReadError:
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read error", "An error occurred reading from the SIMM.");
if (readVerifying)
{
if (verifyBuffer)
{
verifyBuffer->close();
delete verifyBuffer;
}
verifyBuffer = NULL;
if (verifyArray) delete verifyArray;
verifyArray = NULL;
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Verify error", "An error occurred reading the SIMM contents for verification.");
}
else
{
if (readFile)
{
readFile->close();
delete readFile;
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read error", "An error occurred reading from the SIMM.");
}
break;
case ReadCancelled:
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read cancelled", "The read operation was cancelled.");
if (readVerifying)
{
if (verifyBuffer)
{
verifyBuffer->close();
delete verifyBuffer;
}
verifyBuffer = NULL;
if (verifyArray) delete verifyArray;
verifyArray = NULL;
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Verify cancelled", "The verify operation was cancelled.");
}
else
{
if (readFile)
{
readFile->close();
delete readFile;
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read cancelled", "The read operation was cancelled.");
}
break;
case ReadTimedOut:
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read timed out", "The read operation timed out.");
if (readVerifying)
{
if (verifyBuffer)
{
verifyBuffer->close();
delete verifyBuffer;
}
verifyBuffer = NULL;
if (verifyArray) delete verifyArray;
verifyArray = NULL;
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Verify timed out", "The verify operation timed out.");
}
else
{
if (readFile)
{
readFile->close();
delete readFile;
readFile = NULL;
}
ui->pages->setCurrentWidget(ui->controlPage);
QMessageBox::warning(this, "Read timed out", "The read operation timed out.");
}
break;
}
}
@ -373,6 +625,19 @@ void MainWindow::programmerBoardDisconnectedDuringOperation()
{
ui->pages->setCurrentWidget(ui->notConnectedPage);
ui->actionUpdate_firmware->setEnabled(false);
// Make sure any files have been closed if we were in the middle of something.
if (writeFile)
{
writeFile->close();
delete writeFile;
writeFile = NULL;
}
if (readFile)
{
readFile->close();
delete readFile;
readFile = NULL;
}
QMessageBox::warning(this, "Programmer lost connection", "Lost contact with the programmer board. Unplug it, plug it back in, and try again.");
}

View File

@ -2,6 +2,9 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFile>
#include <QBuffer>
#include <QByteArray>
#include "programmer.h"
namespace Ui {
@ -59,7 +62,12 @@ private:
Ui::MainWindow *ui;
bool writeFileValid;
bool readFileValid;
QFile *writeFile;
QFile *readFile;
QBuffer *verifyBuffer;
QByteArray *verifyArray;
QString electricalTestString;
bool readVerifying;
void resetAndShowStatusPage();
};

View File

@ -81,6 +81,16 @@
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="verifyAfterWriteBox">
<property name="text">
<string>Verify contents after write</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">

View File

@ -160,19 +160,23 @@ Programmer::~Programmer()
delete serialPort;
}
void Programmer::readSIMMToFile(QString filename)
void Programmer::readSIMM(QIODevice *device)
{
readFile = new QFile(filename);
readFile->open(QFile::WriteOnly);
//readFile = new QFile(filename);
//readFile->open(QFile::WriteOnly);
//lenRead = 0;
//lenRemaining = _simmCapacity;
readDevice = device;
lenRead = 0;
lenRemaining = _simmCapacity;
startProgrammerCommand(ReadChips, ReadSIMMWaitingStartReply);
}
void Programmer::writeFileToSIMM(QString filename)
void Programmer::writeToSIMM(QIODevice *device)
{
writeFile = new QFile(filename);
/*writeFile = new QFile(filename);
if (!writeFile->open(QFile::ReadOnly))
{
curState = WaitingForNextCommand;
@ -190,6 +194,21 @@ void Programmer::writeFileToSIMM(QString filename)
lenWritten = 0;
writeLenRemaining = writeFile->size();
startProgrammerCommand(EraseChips, WriteSIMMWaitingEraseReply);
}*/
writeDevice = device;
if (writeDevice->size() > _simmCapacity)
{
curState = WaitingForNextCommand;
emit writeStatusChanged(WriteFileTooBig);
return;
}
else
{
lenWritten = 0;
writeLenRemaining = writeDevice->size();
startProgrammerCommand(EraseChips, WriteSIMMWaitingEraseReply);
}
}
@ -236,10 +255,9 @@ void Programmer::handleChar(uint8_t c)
break;
case CommandReplyError:
qDebug() << "Error erasing chips.";
writeFile->close();
curState = WaitingForNextCommand;
emit writeStatusChanged(WriteEraseFailed);
closePort();
emit writeStatusChanged(WriteEraseFailed);
break;
}
break;
@ -264,10 +282,9 @@ void Programmer::handleChar(uint8_t c)
break;
case CommandReplyError:
qDebug() << "Error entering write mode.";
writeFile->close();
curState = WaitingForNextCommand;
emit writeStatusChanged(WriteError);
closePort();
emit writeStatusChanged(WriteError);
break;
}
@ -288,7 +305,7 @@ void Programmer::handleChar(uint8_t c)
}
// Read the chunk from the file!
QByteArray thisChunk = writeFile->read(chunkSize);
QByteArray thisChunk = writeDevice->read(chunkSize);
// If it isn't a WRITE_CHUNK_SIZE chunk, pad the rest of it with 0xFFs (unprogrammed bytes)
// so the total chunk size is WRITE_CHUNK_SIZE, since that's what the programmer board expects.
@ -311,10 +328,9 @@ void Programmer::handleChar(uint8_t c)
case ProgrammerWriteError:
default:
qDebug() << "Error writing to chips.";
writeFile->close();
curState = WaitingForNextCommand;
emit writeStatusChanged(WriteError);
closePort();
emit writeStatusChanged(WriteError);
break;
}
break;
@ -323,19 +339,17 @@ void Programmer::handleChar(uint8_t c)
switch (c)
{
case ProgrammerWriteOK:
writeFile->close();
curState = WaitingForNextCommand;
qDebug() << "Write success at end";
emit writeStatusChanged(WriteComplete);
closePort();
emit writeStatusChanged(WriteComplete);
break;
case ProgrammerWriteError:
default:
qDebug() << "Write failure at end";
curState = WaitingForNextCommand;
writeFile->close();
emit writeStatusChanged(WriteError);
closePort();
emit writeStatusChanged(WriteError);
break;
}
@ -355,14 +369,16 @@ void Programmer::handleChar(uint8_t c)
case CommandReplyInvalid:
default:
curState = WaitingForNextCommand;
emit electricalTestStatusChanged(ElectricalTestCouldntStart);
closePort();
emit electricalTestStatusChanged(ElectricalTestCouldntStart);
}
break;
case ElectricalTestWaitingNextStatus:
switch (c)
{
case ProgrammerElectricalTestDone:
curState = WaitingForNextCommand;
closePort();
if (electricalTestErrorCounter > 0)
{
emit electricalTestStatusChanged(ElectricalTestFailed);
@ -371,8 +387,6 @@ void Programmer::handleChar(uint8_t c)
{
emit electricalTestStatusChanged(ElectricalTestPassed);
}
curState = WaitingForNextCommand;
closePort();
break;
case ProgrammerElectricalTestFail:
electricalTestErrorCounter++;
@ -409,8 +423,8 @@ void Programmer::handleChar(uint8_t c)
case CommandReplyError:
case CommandReplyInvalid:
default:
emit readStatusChanged(ReadError);
curState = WaitingForNextCommand;
emit readStatusChanged(ReadError);
break;
}
break;
@ -426,13 +440,14 @@ void Programmer::handleChar(uint8_t c)
break;
case ProgrammerReadError:
default:
emit readStatusChanged(ReadError);
curState = WaitingForNextCommand;
closePort();
emit readStatusChanged(ReadError);
break;
}
break;
case ReadSIMMWaitingData:
readFile->write((const char *)&c, 1);
readDevice->write((const char *)&c, 1);
lenRead++;
if (--readChunkLenRemaining == 0)
{
@ -448,13 +463,11 @@ void Programmer::handleChar(uint8_t c)
case ProgrammerReadFinished:
curState = WaitingForNextCommand;
closePort();
readFile->close();
emit readStatusChanged(ReadComplete);
break;
case ProgrammerReadConfirmCancel:
curState = WaitingForNextCommand;
closePort();
readFile->close();
emit readStatusChanged(ReadCancelled);
break;
case ProgrammerReadMoreData:
@ -594,6 +607,8 @@ void Programmer::handleChar(uint8_t c)
}
break;
case IdentificationAwaitingDoneReply:
curState = WaitingForNextCommand;
closePort();
if (c == ProgrammerIdentifyDone)
{
emit identificationStatusChanged(IdentificationComplete);
@ -602,7 +617,6 @@ void Programmer::handleChar(uint8_t c)
{
emit identificationStatusChanged(IdentificationError);
}
curState = WaitingForNextCommand;
break;
// WRITE BOOTLOADER PROGRAM STATE HANDLERS
@ -615,26 +629,26 @@ void Programmer::handleChar(uint8_t c)
}
else
{
emit firmwareFlashStatusChanged(FirmwareFlashError);
curState = WaitingForNextCommand;
closePort();
firmwareFile->close();
emit firmwareFlashStatusChanged(FirmwareFlashError);
}
break;
case BootloaderEraseProgramWaitingFinishReply:
if (c == BootloaderWriteOK)
{
emit firmwareFlashStatusChanged(FirmwareFlashComplete);
curState = WaitingForNextCommand;
closePort();
firmwareFile->close();
emit firmwareFlashStatusChanged(FirmwareFlashComplete);
}
else
{
emit firmwareFlashStatusChanged(FirmwareFlashError);
curState = WaitingForNextCommand;
closePort();
firmwareFile->close();
emit firmwareFlashStatusChanged(FirmwareFlashError);
}
break;
case BootloaderEraseProgramWaitingWriteMoreReply:
@ -670,10 +684,10 @@ void Programmer::handleChar(uint8_t c)
}
else
{
emit firmwareFlashStatusChanged(FirmwareFlashError);
curState = WaitingForNextCommand;
closePort();
firmwareFile->close();
emit firmwareFlashStatusChanged(FirmwareFlashError);
}
break;
case BootloaderEraseProgramWaitingWriteReply:
@ -693,10 +707,10 @@ void Programmer::handleChar(uint8_t c)
}
else
{
emit firmwareFlashStatusChanged(FirmwareFlashError);
curState = WaitingForNextCommand;
closePort();
firmwareFile->close();
emit firmwareFlashStatusChanged(FirmwareFlashError);
}
break;

View File

@ -3,6 +3,7 @@
#include <QObject>
#include <QFile>
#include <QIODevice>
#include <qextserialport.h>
#include <qextserialenumerator.h>
#include <stdint.h>
@ -77,8 +78,8 @@ class Programmer : public QObject
public:
explicit Programmer(QObject *parent = 0);
virtual ~Programmer();
void readSIMMToFile(QString filename);
void writeFileToSIMM(QString filename);
void readSIMM(QIODevice *device);
void writeToSIMM(QIODevice *device);
void runElectricalTest();
QString electricalTestPinName(uint8_t index);
void identifySIMMChips();
@ -113,8 +114,10 @@ signals:
public slots:
private:
QFile *readFile;
QFile *writeFile;
//QFile *readFile;
//QFile *writeFile;
QIODevice *readDevice;
QIODevice *writeDevice;
QFile *firmwareFile;
QextSerialPort *serialPort;