diff --git a/qt5_src/Bootloader/Comm.h b/qt5_src/Bootloader/Comm.h index ba50532..0c1b941 100644 --- a/qt5_src/Bootloader/Comm.h +++ b/qt5_src/Bootloader/Comm.h @@ -139,18 +139,6 @@ public: unsigned char config7HMask; unsigned char pad[USB_PACKET_SIZE_WITH_REPORT_ID - 29]; }PIC18; - struct - { - unsigned char command; - uint16_t bootloaderVersion; - uint16_t applicationVersion; - uint32_t signatureAddress; - uint16_t signatureValue; - uint32_t erasePageSize; - #warning Replace with real stuff when implemented. - //uint16_t configxxMask... - //unsigned char pad[USB_PACKET_SIZE_WITH_REPORT_ID - XX]; - }PIC24; }; diff --git a/qt5_src/Bootloader/IBMPlexSans-Light.ttf b/qt5_src/Bootloader/IBMPlexSans-Light.ttf deleted file mode 100644 index 761e3b7..0000000 Binary files a/qt5_src/Bootloader/IBMPlexSans-Light.ttf and /dev/null differ diff --git a/qt5_src/Bootloader/IBMPlexSans-Medium.ttf b/qt5_src/Bootloader/IBMPlexSans-Medium.ttf deleted file mode 100644 index e7b9e78..0000000 Binary files a/qt5_src/Bootloader/IBMPlexSans-Medium.ttf and /dev/null differ diff --git a/qt5_src/Bootloader/IBMPlexSans-Regular.ttf b/qt5_src/Bootloader/IBMPlexSans-Regular.ttf deleted file mode 100644 index b43625f..0000000 Binary files a/qt5_src/Bootloader/IBMPlexSans-Regular.ttf and /dev/null differ diff --git a/qt5_src/Bootloader/MainWindow.cpp b/qt5_src/Bootloader/MainWindow.cpp index 6b312ff..8ba1c53 100644 --- a/qt5_src/Bootloader/MainWindow.cpp +++ b/qt5_src/Bootloader/MainWindow.cpp @@ -95,25 +95,18 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi timer = new QTimer(); ui->setupUi(this); - setWindowTitle(APPLICATION + QString(" v") + VERSION); - - //ui->menuBar->setVisible(false); - //ui->mainToolBar->setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); + setWindowTitle(QCoreApplication::applicationName() + QString(" v") + VERSION); // by default hide the advanced controls - on_checkBoxAdvancedMode_stateChanged(0); + // (qtimer with 0 delay is a dumb way to make sure this is called after the window finishes updating geometry) + QTimer::singleShot(0, this, [this]() { + on_checkBoxAdvancedMode_stateChanged(0); + }); QSettings settings; - settings.beginGroup("MainWindow"); - - settings.endGroup(); - settings.beginGroup("WriteOptions"); writeFlash = settings.value("writeFlash", true).toBool(); - //writeConfig = settings.value("writeConfig", false).toBool(); - writeConfig = false; //Force user to manually re-enable it every time they re-launch the application. Safer that way. writeEeprom = settings.value("writeEeprom", false).toBool(); - eraseDuringWrite = true; settings.endGroup(); comm = new Comm(); @@ -124,13 +117,66 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi qRegisterMetaType("Comm::ErrorCode"); + connect(ui->btnFlashFirmware, &QPushButton::clicked, this, [=](){ + future = QtConcurrent::run([this](){ + Comm::ErrorCode subResult; + //Update the progress bar so the user knows things are happening. + emit SetProgressBar(3); + //First erase the entire device. + emit IoWithDeviceStateChanged("(1/3) Erasing device..."); + subResult = EraseDevice(); + if (subResult != Comm::Success) + { + emit IoWithDeviceStateChanged("Erasing device failed!"); + QMessageBox::critical(this, "Device Flashing Failed", + "An error ocurred while erasing the device. Please disconnect " + "and reconnect the device and try again."); + return subResult; + } + //then write the new firmware to the device + emit IoWithDeviceStateChanged("(2/3) Writing device..."); + subResult = WriteDevice(); + if (subResult != Comm::Success) + { + emit IoWithDeviceStateChanged("Writing device failed!"); + QMessageBox::critical(this, "Device Flashing Failed", + "An error ocurred while writing the device. Please disconnect " + "and reconnect the device and try again."); + return subResult; + } + //finally verify the device's memory and write the signature word + emit IoWithDeviceStateChanged("(3/3) Verifying device..."); + subResult = VerifyDevice(); + emit SetProgressBar(100); + if (subResult != Comm::Success) + { + emit IoWithDeviceStateChanged("Verifying device failed!"); + QMessageBox::critical(this, "Device Flashing Failed", + "An error ocurred while verifying the device. Please disconnect " + "and reconnect the device and try again."); + return subResult; + } + emit AppendString("Firmware was sucessfully flashed"); + emit IoWithDeviceStateChanged("Ready."); + + emit UserMustResetPrompt(); + + return Comm::Success; + }); + ui->plainTextEdit->clear(); + ui->plainTextEdit->appendPlainText("Starting Erase/Program/Verify Sequence."); + ui->plainTextEdit->appendPlainText("Do not unplug device or disconnect power until the operation is fully complete."); + ui->plainTextEdit->appendPlainText(" "); + }); + connect(timer, SIGNAL(timeout()), this, SLOT(Connection())); connect(this, SIGNAL(IoWithDeviceCompleted(QString,Comm::ErrorCode,double)), this, SLOT(IoWithDeviceComplete(QString,Comm::ErrorCode,double))); connect(this, SIGNAL(IoWithDeviceStarted(QString)), this, SLOT(IoWithDeviceStart(QString))); connect(this, SIGNAL(AppendString(QString)), this, SLOT(AppendStringToTextbox(QString))); connect(this, SIGNAL(SetProgressBar(int)), this, SLOT(UpdateProgressBar(int))); connect(comm, SIGNAL(SetProgressBar(int)), this, SLOT(UpdateProgressBar(int))); - + connect(this, &MainWindow::IoWithDeviceStateChanged, this, &MainWindow::IoWithDeviceStateChange); + connect(this, &MainWindow::UserMustResetPrompt, this, &MainWindow::PromptUserToReset); //Assume initally that the USB device that we are trying to find is using the default VID/PID. DeviceVID = DEFAULT_VID; @@ -189,9 +235,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi } } - - - //Make initial check to see if the USB device is attached comm->PollUSB(DeviceVID, DevicePID); if(comm->isConnected()) @@ -204,16 +247,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi } else { - //ui->plainTextEdit->appendPlainText("Device not detected. Verify device is attached and in firmware update mode."); + ui->plainTextEdit->appendPlainText("Device not detected. Verify device is attached and in firmware update mode."); hexOpen = false; setBootloadEnabled(false); emit SetProgressBar(0); } - timer->start(1000); //Check for future USB connection status changes every 1000 milliseconds. - //Check if the user ran the .exe with extensions pointing staight to the hex file of interest to be programmed. //If the device is connected, and the extra info was provided, jump straight to erase/program/verify operation //and then exit the program. This is useful if you want to use the bootloader in a more production or automated @@ -278,24 +319,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi } } - - - - - MainWindow::~MainWindow() { QSettings settings; - - settings.beginGroup("MainWindow"); - settings.setValue("size", size()); - settings.setValue("pos", pos()); - settings.setValue("fileName", fileName); - settings.endGroup(); - settings.beginGroup("WriteOptions"); settings.setValue("writeFlash", writeFlash); - settings.setValue("writeConfig", writeConfig); settings.setValue("writeEeprom", writeEeprom); settings.endGroup(); @@ -313,7 +341,6 @@ MainWindow::~MainWindow() void MainWindow::Connection(void) { bool currStatus = comm->isConnected(); - Comm::ErrorCode result; comm->PollUSB(DeviceVID, DevicePID); @@ -325,20 +352,6 @@ void MainWindow::Connection(void) comm->open(DeviceVID, DevicePID); ui->plainTextEdit->setPlainText("Device Attached."); ui->plainTextEdit->appendPlainText("Connecting..."); - if(writeConfig) - { - //ui->plainTextEdit->appendPlainText("Disabling Erase button to prevent accidental erasing of the configuration words without reprogramming them\n"); - writeConfig = true; - result = comm->LockUnlockConfig(false); - if(result == Comm::Success) - { - ui->plainTextEdit->appendPlainText("Unlocked Configuration bits successfully\n"); - } - } - else - { - writeConfig = false; - } GetQuery(); } else @@ -346,6 +359,9 @@ void MainWindow::Connection(void) qWarning("Closing device."); comm->close(); ui->plainTextEdit->setPlainText("Device Detached."); + ui->lblDeviceConnected->setText("Not Connected"); + ui->lblDeviceConnected->setStyleSheet("QLabel { background-color : red; }"); + ui->lblDeviceStatusMsg->setText("Device not detected. Please connect the dancepad interface's USB cable to this computer."); hexOpen = false; setBootloadEnabled(false); emit SetProgressBar(0); @@ -355,14 +371,18 @@ void MainWindow::Connection(void) void MainWindow::setBootloadEnabled(bool enable) { - ui->action_Settings->setEnabled(enable); - ui->actionErase_Device->setEnabled(enable && !writeConfig); - ui->actionWrite_Device->setEnabled(enable && hexOpen); - //ui->actionExit->setEnabled(enable); - ui->action_Verify_Device->setEnabled(enable && hexOpen); - //ui->actionOpen->setEnabled(enable); - ui->actionBlank_Check->setEnabled(enable && !writeConfig); - ui->actionReset_Device->setEnabled(enable); + ui->groupFlashFirmware->setEnabled(enable && hexOpen); + ui->groupFirmwareFile->setEnabled(enable); + ui->btnResetDevice->setEnabled(enable); + + ui->progressBar->reset(); + + if (!enable) + { + ui->lblFlashStatus->setText("Not ready."); + ui->lblDeviceBootloaderVer->setText(""); + ui->lblDeviceAppFWVer->setText(""); + } } void MainWindow::setBootloadBusy(bool busy) @@ -378,15 +398,9 @@ void MainWindow::setBootloadBusy(bool busy) timer->start(1000); } - ui->action_Settings->setEnabled(!busy); - ui->actionErase_Device->setEnabled(!busy && !writeConfig); - ui->actionWrite_Device->setEnabled(!busy && hexOpen); - //ui->actionExit->setEnabled(!busy); - ui->action_Verify_Device->setEnabled(!busy && hexOpen); - ui->btnFwBrowse->setEnabled(!busy); - ui->action_Settings->setEnabled(!busy); - ui->actionBlank_Check->setEnabled(!busy && !writeConfig); - ui->actionReset_Device->setEnabled(!busy); + ui->btnFlashFirmware->setEnabled(!busy && hexOpen); + ui->groupFirmwareFile->setEnabled(!busy); + ui->btnResetDevice->setEnabled(!busy); } void MainWindow::IoWithDeviceStart(QString msg) @@ -407,8 +421,6 @@ void MainWindow::UpdateProgressBar(int newValue) ui->progressBar->setValue(newValue); } - - void MainWindow::IoWithDeviceComplete(QString msg, Comm::ErrorCode result, double time) { QTextStream ss(&msg); @@ -440,24 +452,42 @@ void MainWindow::IoWithDeviceComplete(QString msg, Comm::ErrorCode result, doubl } ui->plainTextEdit->appendPlainText(msg); + if (result != Comm::Success) + { + ui->lblFlashStatus->setText(*ss.string()); + QMessageBox::critical(this, "Error", *ss.string()); + } } -void MainWindow::on_action_Verify_Device_triggered() +void MainWindow::IoWithDeviceStateChange(QString msg) { - future = QtConcurrent::run(this, &MainWindow::VerifyDevice); + ui->lblFlashStatus->setText(msg); +} + +void MainWindow::PromptUserToReset() +{ + QMessageBox::StandardButton resButton; + resButton = QMessageBox::information(this, "Firmware was sucessfully flashed", + "Reset device now?" + "(Note: Device must be reset or physically disconnected and " + "reconnected before it can be used.)", + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + //reset device if user chose to + if (resButton == QMessageBox::Yes) + on_btnResetDevice_clicked(); } //Routine that verifies the contents of the non-voltaile memory regions in the device, after an erase/programming cycle. //This function requests the memory contents of the device, then compares it against the parsed .hex file data to make sure //The locations that got programmed properly match. -void MainWindow::VerifyDevice() +Comm::ErrorCode MainWindow::VerifyDevice() { Comm::ErrorCode result; DeviceData::MemoryRange deviceRange, hexRange; QTime elapsed; unsigned int i, j; - unsigned int arrayIndex; bool failureDetected = false; unsigned char flashData[MAX_ERASE_BLOCK_SIZE]; unsigned char hexEraseBlockData[MAX_ERASE_BLOCK_SIZE]; @@ -474,11 +504,8 @@ void MainWindow::VerifyDevice() elapsed.start(); foreach(deviceRange, deviceData->ranges) { - if(writeFlash && (deviceRange.type == PROGRAM_MEMORY)) + if(deviceRange.type == PROGRAM_MEMORY) { - //elapsed.start(); - //emit IoWithDeviceStarted("Verifying Device's Program Memory..."); - result = comm->GetData(deviceRange.start, device->bytesPerPacket, device->bytesPerAddressFLASH, @@ -490,7 +517,6 @@ void MainWindow::VerifyDevice() { failureDetected = true; qWarning("Error reading device."); - //emit IoWithDeviceCompleted("Verifying Device's Program Memory", result, ((double)elapsed.elapsed()) / 1000); } //Search through all of the programmable memory regions from the parsed .hex file data. @@ -538,7 +564,7 @@ void MainWindow::VerifyDevice() } qWarning("Failed verify at address 0x%x", i); emit IoWithDeviceCompleted("Verify", Comm::Fail, ((double)elapsed.elapsed()) / 1000); - return; + return Comm::Fail; } }//if(deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j] != hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j]) }//for(j = 0; j < device->bytesPerAddressFLASH; j++) @@ -549,9 +575,6 @@ void MainWindow::VerifyDevice() }//if(writeFlash && (deviceRange.type == PROGRAM_MEMORY)) else if(writeEeprom && (deviceRange.type == EEPROM_MEMORY)) { - //elapsed.start(); - //emit IoWithDeviceStarted("Verifying Device's EEPROM Memory..."); - result = comm->GetData(deviceRange.start, device->bytesPerPacket, device->bytesPerAddressEEPROM, @@ -590,7 +613,7 @@ void MainWindow::VerifyDevice() qWarning("Device: 0x%x Hex: 0x%x", deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j], hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressFLASH)+j]); qWarning("Failed verify at address 0x%x", i); emit IoWithDeviceCompleted("Verify EEPROM Memory", Comm::Fail, ((double)elapsed.elapsed()) / 1000); - return; + return Comm::Fail; } } } @@ -598,87 +621,6 @@ void MainWindow::VerifyDevice() }//foreach(hexRange, hexData->ranges) //emit IoWithDeviceCompleted("Verifying", Comm::Success, ((double)elapsed.elapsed()) / 1000); }//else if(writeEeprom && (deviceRange.type == EEPROM_MEMORY)) - else if(writeConfig && (deviceRange.type == CONFIG_MEMORY)) - { - //elapsed.start(); - //emit IoWithDeviceStarted("Verifying Device's Config Words..."); - - result = comm->GetData(deviceRange.start, - device->bytesPerPacket, - device->bytesPerAddressConfig, - device->bytesPerWordConfig, - deviceRange.end, - deviceRange.pDataBuffer); - - if(result != Comm::Success) - { - failureDetected = true; - qWarning("Error reading device."); - //emit IoWithDeviceCompleted("Verifying Device's Config Words", result, ((double)elapsed.elapsed()) / 1000); - } - - //Search through all of the programmable memory regions from the parsed .hex file data. - //For each of the programmable memory regions found, if the region also overlaps a region - //that was included in the device programmed area (which just got read back with GetData()), - //then verify both the parsed hex contents and read back data match. - foreach(hexRange, hexData->ranges) - { - if(deviceRange.start == hexRange.start) - { - //For this entire programmable memory address range, check to see if the data read from the device exactly - //matches what was in the hex file. - for(i = deviceRange.start; i < deviceRange.end; i++) - { - //For each byte of each device address (1 on PIC18, 2 on PIC24, since flash memory is 16-bit WORD array) - for(j = 0; j < device->bytesPerAddressConfig; j++) - { - //Compute an index into the device and hex data arrays, based on the current i and j values. - arrayIndex = ((i - deviceRange.start) * device->bytesPerAddressConfig)+j; - - //Check if the device response data matches the data we parsed from the original input .hex file. - if(deviceRange.pDataBuffer[arrayIndex] != hexRange.pDataBuffer[arrayIndex]) - { - //A mismatch was detected. Perform additional checks to make sure it was a real/unexpected verify failure. - - //Check if this is a PIC24 device and we are looking at the "phantom byte" - //(upper byte [j = 1] of odd address [i%2 == 1] 16-bit flash words). If the hex data doesn't match - //the device (which should be = 0x00 for these locations), this isn't a real verify - //failure, since value is a don't care anyway. This could occur if the hex file imported - //doesn't contain all locations, and we "filled" the region with pure 0xFFFFFFFF, instead of 0x00FFFFFF - //when parsing the hex file. - if((device->family == Device::PIC24) && ((i % 2) == 1) && (j == 1)) - { - //Not a real verify failure, phantom byte is unimplemented and is a don't care. - }//Make further special checks for PIC18 non-J devices - else if((device->family == Device::PIC18) && (deviceRange.start == 0x300000) && ((i == 0x300004) || (i == 0x300007))) - { - //The "CONFIG3L" and "CONFIG4H" locations (0x300004 and 0x300007) on PIC18 non-J USB devices - //are unimplemented and should be masked out from the verify operation. - } - else - { - //If the data wasn't a match, and this wasn't a PIC24 phantom byte, then if we get - //here this means we found a true verify failure. - failureDetected = true; - if(device->family == Device::PIC24) - { - qWarning("Device: 0x%x Hex: 0x%x", *(uint16_t*)&deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j], *(uint16_t*)&hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j]); - } - else - { - qWarning("Device: 0x%x Hex: 0x%x", deviceRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j], hexRange.pDataBuffer[((i - deviceRange.start) * device->bytesPerAddressConfig)+j]); - } - qWarning("Failed verify at address 0x%x", i); - emit IoWithDeviceCompleted("Verify Config Bit Memory", Comm::Fail, ((double)elapsed.elapsed()) / 1000); - return; - } - } - } - }//for(i = deviceRange.start; i < deviceRange.end; i++) - }//if(deviceRange.start == hexRange.start) - }//foreach(hexRange, hexData->ranges) - //emit IoWithDeviceCompleted("Verifying", Comm::Success, ((double)elapsed.elapsed()) / 1000); - }//else if(writeConfig && (deviceRange.type == CONFIG_MEMORY)) else { continue; @@ -807,53 +749,41 @@ void MainWindow::VerifyDevice() else { emit IoWithDeviceCompleted("Verify", Comm::Success, ((double)elapsed.elapsed()) / 1000); - emit AppendString("Erase/Program/Verify sequence completed successfully."); - emit AppendString("You may now unplug or reset the device."); + emit AppendString("Device verified successfully."); //Set flags only used when the program was invoked from the console with extra parameters for auto-program and close behavior. consoleEraseProgramVerifiedOkay = true; consoleInvokedEraseProgramVerifyComplete = true; } - emit SetProgressBar(100); //Set progress bar to 100% + return failureDetected ? Comm::Fail : Comm::Success; }//void MainWindow::VerifyDevice() - -//Gets called when the user clicks to program button in the GUI. -void MainWindow::on_actionWrite_Device_triggered() -{ - future = QtConcurrent::run(this, &MainWindow::WriteDevice); - ui->plainTextEdit->clear(); - ui->plainTextEdit->appendPlainText("Starting Erase/Program/Verify Sequence."); - ui->plainTextEdit->appendPlainText("Do not unplug device or disconnect power until the operation is fully complete."); - ui->plainTextEdit->appendPlainText(" "); -} - - //This thread programs previously parsed .hex file data into the device's programmable memory regions. -void MainWindow::WriteDevice(void) +Comm::ErrorCode MainWindow::WriteDevice(void) { QTime elapsed; Comm::ErrorCode result; DeviceData::MemoryRange hexRange; - //Update the progress bar so the user knows things are happening. - emit SetProgressBar(3); - //First erase the entire device. - EraseDevice(); - //Now begin re-programming each section based on the info we obtained when //we parsed the user's .hex file. + // NOTE: The bootloader allows writing config bits. This functionality remains in + // the bootloader firmware but has been removed from this utility because the end user + // will never need to use it. + + // NOTE 2: The original version of this utility provided a settings dialog to select which + // sections of flash memory should be written. This has been removed and this utility will + // instead always write only program flash. The ability to write EEPROM has been retained, + // however it is unused. + emit IoWithDeviceStarted("Writing Device..."); elapsed.start(); foreach(hexRange, hexData->ranges) { - if(writeFlash && (hexRange.type == PROGRAM_MEMORY)) + if(hexRange.type == PROGRAM_MEMORY) { - //emit IoWithDeviceStarted("Writing Device Program Memory..."); - //elapsed.start(); - result = comm->Program(hexRange.start, device->bytesPerPacket, device->bytesPerAddressFLASH, @@ -864,9 +794,6 @@ void MainWindow::WriteDevice(void) } else if(writeEeprom && (hexRange.type == EEPROM_MEMORY)) { - //emit IoWithDeviceStarted("Writing Device EEPROM Memory..."); - //elapsed.start(); - result = comm->Program(hexRange.start, device->bytesPerPacket, device->bytesPerAddressEEPROM, @@ -875,125 +802,20 @@ void MainWindow::WriteDevice(void) hexRange.end, hexRange.pDataBuffer); } - else if(writeConfig && (hexRange.type == CONFIG_MEMORY)) - { - //emit IoWithDeviceStarted("Writing Device Config Words..."); - //elapsed.start(); - - result = comm->Program(hexRange.start, - device->bytesPerPacket, - device->bytesPerAddressConfig, - device->bytesPerWordConfig, - device->family, - hexRange.end, - hexRange.pDataBuffer); - } else { continue; } - //emit IoWithDeviceCompleted("Writing", result, ((double)elapsed.elapsed()) / 1000); - if(result != Comm::Success) { qWarning("Programming failed"); - return; + return result; } } emit IoWithDeviceCompleted("Write", result, ((double)elapsed.elapsed()) / 1000); - - VerifyDevice(); -} - -void MainWindow::on_actionBlank_Check_triggered() -{ - future = QtConcurrent::run(this, &MainWindow::BlankCheckDevice); -} - -void MainWindow::BlankCheckDevice(void) -{ - QTime elapsed; - Comm::ErrorCode result; - DeviceData::MemoryRange deviceRange; - - elapsed.start(); - - foreach(deviceRange, deviceData->ranges) - { - if(writeFlash && (deviceRange.type == PROGRAM_MEMORY)) - { - emit IoWithDeviceStarted("Blank Checking Device's Program Memory..."); - - result = comm->GetData(deviceRange.start, - device->bytesPerPacket, - device->bytesPerAddressFLASH, - device->bytesPerWordFLASH, - deviceRange.end, - deviceRange.pDataBuffer); - - - if(result != Comm::Success) - { - qWarning("Blank Check failed"); - emit IoWithDeviceCompleted("Blank Checking Program Memory", result, ((double)elapsed.elapsed()) / 1000); - return; - } - - for(unsigned int i = 0; i < ((deviceRange.end - deviceRange.start) * device->bytesPerAddressFLASH); i++) - { - if((deviceRange.pDataBuffer[i] != 0xFF) && !((device->family == Device::PIC24) && ((i % 4) == 3))) - { - qWarning("Failed blank check at address 0x%x", deviceRange.start + i); - qWarning("The value was 0x%x", deviceRange.pDataBuffer[i]); - emit IoWithDeviceCompleted("Blank Check", Comm::Fail, ((double)elapsed.elapsed()) / 1000); - return; - } - } - emit IoWithDeviceCompleted("Blank Checking Program Memory", Comm::Success, ((double)elapsed.elapsed()) / 1000); - } - else if(writeEeprom && deviceRange.type == EEPROM_MEMORY) - { - emit IoWithDeviceStarted("Blank Checking Device's EEPROM Memory..."); - - result = comm->GetData(deviceRange.start, - device->bytesPerPacket, - device->bytesPerAddressEEPROM, - device->bytesPerWordEEPROM, - deviceRange.end, - deviceRange.pDataBuffer); - - - if(result != Comm::Success) - { - qWarning("Blank Check failed"); - emit IoWithDeviceCompleted("Blank Checking EEPROM Memory", result, ((double)elapsed.elapsed()) / 1000); - return; - } - - for(unsigned int i = 0; i < ((deviceRange.end - deviceRange.start) * device->bytesPerWordEEPROM); i++) - { - if(deviceRange.pDataBuffer[i] != 0xFF) - { - qWarning("Failed blank check at address 0x%x + 0x%x", deviceRange.start, i); - qWarning("The value was 0x%x", deviceRange.pDataBuffer[i]); - emit IoWithDeviceCompleted("Blank Check", Comm::Fail, ((double)elapsed.elapsed()) / 1000); - return; - } - } - emit IoWithDeviceCompleted("Blank Checking EEPROM Memory", Comm::Success, ((double)elapsed.elapsed()) / 1000); - } - else - { - continue; - } - } -} - -void MainWindow::on_actionErase_Device_triggered() -{ - future = QtConcurrent::run(this, &MainWindow::EraseDevice); + return Comm::Success; } void MainWindow::on_checkBoxAdvancedMode_stateChanged(int state) @@ -1015,29 +837,26 @@ void MainWindow::on_checkBoxAdvancedMode_stateChanged(int state) } } -void MainWindow::EraseDevice(void) +Comm::ErrorCode MainWindow::EraseDevice(void) { QTime elapsed; Comm::ErrorCode result; Comm::BootInfo bootInfo; + emit IoWithDeviceStarted("Erasing Device... (no status update until complete, may take several seconds)"); + elapsed.start(); - //if(writeFlash || writeEeprom) + result = comm->Erase(); + if(result != Comm::Success) { - emit IoWithDeviceStarted("Erasing Device... (no status update until complete, may take several seconds)"); - elapsed.start(); - - result = comm->Erase(); - if(result != Comm::Success) - { - emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000); - return; - } - - result = comm->ReadBootloaderInfo(&bootInfo); - emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000); + return result; } + + result = comm->ReadBootloaderInfo(&bootInfo); + + emit IoWithDeviceCompleted("Erase", result, ((double)elapsed.elapsed()) / 1000); + return result; } //Executes when the user clicks the open hex file button on the main form. @@ -1069,13 +888,12 @@ void MainWindow::LoadFile(QString newFileName) HexImporter import; HexImporter::ErrorCode result; - Comm::ErrorCode commResultCode; int i; hexData->ranges.clear(); //Print some debug info to the debug window. - qDebug(QString("Total Programmable Regions Reported by Device: " + QString::number(deviceData->ranges.count(), 10)).toLatin1()); + qDebug("Total Programmable Regions Reported by Device: %d", deviceData->ranges.count()); //First duplicate the deviceData programmable region list and //allocate some RAM buffers to hold the hex data that we are about to import. @@ -1123,8 +941,7 @@ void MainWindow::LoadFile(QString newFileName) hexData->ranges.append(HexBuffer); //Print info regarding the programmable memory region to the debug window. - qDebug(QString("Device Programmable Region: [" + QString::number(HexBuffer.start, 16).toUpper() + " - " + - QString::number(HexBuffer.end, 16).toUpper() +")").toLatin1()); + qDebug("Device Programmable Region: [0x%X - 0x%X]", HexBuffer.start, HexBuffer.end); } //Import the hex file data into the hexData->ranges[].pDataBuffer buffers. @@ -1165,29 +982,9 @@ void MainWindow::LoadFile(QString newFileName) return; } - //Check if the user has imported a .hex file that doesn't contain config bits in it, - //even though the user is planning on re-programming the config bits section. - if(writeConfig && (import.hasConfigBits == false) && device->hasConfig()) - { - //The user had config bit reprogramming selected, but the hex file opened didn't have config bit - //data in it. We should automatically prevent config bit programming, to avoid leaving the device - //in a broken state following the programming cycle. - commResultCode = comm->LockUnlockConfig(true); //Lock the config bits. - if(commResultCode != Comm::Success) - { - ui->plainTextEdit->appendPlainText("Unexpected internal error encountered. Recommend restarting the application to avoid ""bricking"" the device.\n"); - } - - QMessageBox::warning(this, "Warning!", "This HEX file does not contain config bit information.\n\nAutomatically disabling config bit reprogramming to avoid leaving the device in a state that could prevent further bootloading.", QMessageBox::AcceptRole, QMessageBox::AcceptRole); - writeConfig = false; - } - fileName = newFileName; watchFileName = newFileName; - QSettings settings; - settings.beginGroup("MainWindow"); - stream.setIntegerBase(10); msg.clear(); @@ -1195,6 +992,7 @@ void MainWindow::LoadFile(QString newFileName) QString name = fi.fileName(); stream << "Opened: " << name << "\n"; ui->plainTextEdit->appendPlainText(msg); + ui->lblFlashStatus->setText("Ready."); hexOpen = true; setBootloadEnabled(true); QApplication::restoreOverrideCursor(); @@ -1211,42 +1009,6 @@ void MainWindow::openRecentFile(void) } } -void MainWindow::on_action_About_triggered() -{ - QString msg; - QTextStream stream(&msg); - - stream << "USB HID Bootloader v" << VERSION << "\n"; - stream << "Copyright " << (char)Qt::Key_copyright << " 2011-2013, Microchip Technology Inc.\n\n"; - - stream << "Microchip licenses this software to you solely for use with\n"; - stream << "Microchip products. The software is owned by Microchip and\n"; - stream << "its licensors, and is protected under applicable copyright\n"; - stream << "laws. All rights reserved.\n\n"; - - stream << "SOFTWARE IS PROVIDED \"AS IS.\" MICROCHIP EXPRESSLY\n"; - stream << "DISCLAIMS ANY WARRANTY OF ANY KIND, WHETHER EXPRESS\n"; - stream << "OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED\n"; - stream << "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n"; - stream << "PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT\n"; - stream << "SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL,\n"; - stream << "INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR\n"; - stream << "LOST DATA, HARM TO YOUR EQUIPMENT, COST OF\n"; - stream << "PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR\n"; - stream << "SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT\n"; - stream << "NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR\n"; - stream << "INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.\n\n"; - - stream << "To the fullest extent allowed by law, Microchip and its\n"; - stream << "licensors liability shall not exceed the amount of fees, if any,\n"; - stream << "that you have paid directly to Microchip to use this software.\n\n"; - - stream << "MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON\n"; - stream << "YOUR ACCEPTANCE OF THESE TERMS."; - - QMessageBox::about(this, "About", msg); -} - void MainWindow::GetQuery() { QTime totalTime; @@ -1279,7 +1041,9 @@ void MainWindow::GetQuery() case Comm::Success: wasBootloaderMode = true; ss << "Device Ready"; - //deviceLabel.setText("Connected"); + ui->lblDeviceConnected->setText("Connected"); + ui->lblDeviceConnected->setStyleSheet("QLabel { background-color : green; }"); + ui->lblDeviceStatusMsg->setText(""); break; default: return; @@ -1302,20 +1066,6 @@ void MainWindow::GetQuery() device->bytesPerWordFLASH = 2; device->bytesPerAddressFLASH = 1; break; - case Device::PIC24: - device->bytesPerWordFLASH = 4; - device->bytesPerAddressFLASH = 2; - device->bytesPerWordConfig = 4; - device->bytesPerAddressConfig = 2; - break; - case Device::PIC32: - device->bytesPerWordFLASH = 4; - device->bytesPerAddressFLASH = 1; - break; - case Device::PIC16: - device->bytesPerWordFLASH = 2; - device->bytesPerAddressFLASH = 2; - break; default: device->bytesPerWordFLASH = 2; device->bytesPerAddressFLASH = 1; @@ -1341,7 +1091,7 @@ void MainWindow::GetQuery() qDebug("Device bootloader firmware is v1.01 or newer and supports Extended Query."); //Now fetch the extended query information packet from the USB firmware. comm->ReadExtendedQueryInfo(&extendedBootInfo); - qDebug("Device bootloader firmware version is: " + extendedBootInfo.PIC18.bootloaderVersion); + qDebug("Device bootloader firmware version is: %d", extendedBootInfo.PIC18.bootloaderVersion); } else { @@ -1418,75 +1168,20 @@ void MainWindow::GetQuery() deviceData->ranges.append(range); } + ui->lblDeviceBootloaderVer->setText(QString::number(extendedBootInfo.PIC18.bootloaderVersion)); + QString appVerMsg = (extendedBootInfo.PIC18.applicationVersion > 0) ? + QString::number(extendedBootInfo.PIC18.applicationVersion) : + "No FW on device"; + ui->lblDeviceAppFWVer->setText(appVerMsg); - //Make sure user has allowed at least one region to be programmed - if(!(writeFlash || writeEeprom || writeConfig)) - { - setBootloadEnabled(false); - ui->action_Settings->setEnabled(true); - } - else - setBootloadEnabled(true); + // if the user already loaded a hex file, attempt to load it again for the newly connected device + if (!ui->txtFirmwareFile->text().isEmpty()) + LoadFile(ui->txtFirmwareFile->text()); + + setBootloadEnabled(true); } - - - -void MainWindow::on_action_Settings_triggered() -{ - Comm::ErrorCode result; - Settings* dlg = new Settings(this); - - dlg->enableEepromBox(device->hasEeprom()); - - dlg->setWriteFlash(writeFlash); - dlg->setWriteConfig(writeConfig); - dlg->setWriteEeprom(writeEeprom); - - if(dlg->exec() == QDialog::Accepted) - { - writeFlash = dlg->writeFlash; - writeEeprom = dlg->writeEeprom; - - if(!writeConfig && dlg->writeConfig) - { - ui->plainTextEdit->appendPlainText("Disabling Erase button to prevent accidental erasing of the configuration words without reprogramming them\n"); - writeConfig = true; - hexOpen = false; - result = comm->LockUnlockConfig(false); - if(result == Comm::Success) - { - ui->plainTextEdit->appendPlainText("Unlocked Configuration bits successfully\n"); - GetQuery(); - } - } - else if(writeConfig && !dlg->writeConfig) - { - writeConfig = false; - hexOpen = false; - result = comm->LockUnlockConfig(true); - if(result == Comm::Success) - { - ui->plainTextEdit->appendPlainText("Locked Configuration bits successfully\n"); - GetQuery(); - } - } - - if(!(writeFlash || writeEeprom || writeConfig)) - { - setBootloadEnabled(false); - ui->action_Settings->setEnabled(true); - } - else - { - setBootloadEnabled(true); - } - } - - delete dlg; -} - -void MainWindow::on_actionReset_Device_triggered() +void MainWindow::on_btnResetDevice_clicked() { if(!comm->isConnected()) { diff --git a/qt5_src/Bootloader/MainWindow.h b/qt5_src/Bootloader/MainWindow.h index bdf36fe..17a17d9 100644 --- a/qt5_src/Bootloader/MainWindow.h +++ b/qt5_src/Bootloader/MainWindow.h @@ -61,10 +61,9 @@ public: void GetQuery(void); void LoadFile(QString fileName); - void EraseDevice(void); - void BlankCheckDevice(void); - void WriteDevice(void); - void VerifyDevice(void); + Comm::ErrorCode EraseDevice(void); + Comm::ErrorCode WriteDevice(void); + Comm::ErrorCode VerifyDevice(void); void setBootloadBusy(bool busy); @@ -73,6 +72,8 @@ signals: void IoWithDeviceStarted(QString msg); void AppendString(QString msg); void SetProgressBar(int newValue); + void IoWithDeviceStateChanged(QString msg); + void UserMustResetPrompt(); public slots: void Connection(void); @@ -81,6 +82,8 @@ public slots: void IoWithDeviceStart(QString msg); void AppendStringToTextbox(QString msg); void UpdateProgressBar(int newValue); + void IoWithDeviceStateChange(QString msg); + void PromptUserToReset(); protected: Comm* comm; @@ -95,8 +98,6 @@ protected: bool writeFlash; bool writeEeprom; - bool writeConfig; - bool eraseDuringWrite; bool hexOpen; void setBootloadEnabled(bool enable); @@ -113,16 +114,9 @@ private: private slots: - void on_actionBlank_Check_triggered(); - void on_actionReset_Device_triggered(); - void on_action_Settings_triggered(); - void on_action_Verify_Device_triggered(); - void on_action_About_triggered(); - void on_actionWrite_Device_triggered(); void on_btnFwBrowse_clicked(); - void on_actionErase_Device_triggered(); - void on_checkBoxAdvancedMode_stateChanged(int state); + void on_btnResetDevice_clicked(); }; #endif // MAINWINDOW_H diff --git a/qt5_src/Bootloader/MainWindow.ui b/qt5_src/Bootloader/MainWindow.ui index 182a248..19d932f 100644 --- a/qt5_src/Bootloader/MainWindow.ui +++ b/qt5_src/Bootloader/MainWindow.ui @@ -2,6 +2,14 @@ MainWindowClass + + + 0 + 0 + 481 + 798 + + 481 @@ -22,11 +30,159 @@ + + 11 + + + 11 + + + 11 + + + 11 + + + + + + 0 + 0 + + + + + Segoe UI + 14 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 1em; + padding-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Step 1: Connect Device + + + + 4 + + + + + 0 + + + + + + Segoe UI + 12 + + + + Status + + + + + + + + Segoe UI + 10 + + + + background-color: rgb(255, 0, 0); + + + Not Connected + + + 3 + + + 15 + + + + + + + + + + 0 + 0 + + + + + Segoe UI + 10 + + + + Device not detected. Please connect the dancepad interface's USB cable to this computer. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 0 + 1 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + false + 0 @@ -54,7 +210,7 @@ QGroupBox::title { } - Step 1: Select App FW File + Step 2: Select App FW File @@ -97,6 +253,9 @@ QGroupBox::title { + + false + 0 @@ -124,14 +283,11 @@ QGroupBox::title { } - Step 2: Flash FW to Device + Step 3: Flash FW to Device - - false - 0 @@ -158,7 +314,7 @@ QGroupBox::title { - + Segoe UI @@ -166,7 +322,7 @@ QGroupBox::title { - Flashing Progress + Not ready. @@ -188,127 +344,6 @@ QGroupBox::title { - - - - - 0 - 0 - - - - - Segoe UI - 14 - - - - QGroupBox { - border: 1px solid gray; - border-radius: 9px; - margin-top: 1em; - padding-top: 0.5em; -} - -QGroupBox::title { - subcontrol-origin: margin; - left: 10px; - padding: 0 3px 0 3px; -} - - - Device Information - - - - 4 - - - - - 0 - - - - - - Segoe UI - 12 - - - - Status - - - - - - - - Segoe UI - 10 - - - - background-color: rgb(255, 0, 0); - - - Not Connected - - - 3 - - - 15 - - - - - - - - - - 0 - 0 - - - - - Segoe UI - 10 - - - - Device not detected. Please connect the dancepad interface's USB cable to this computer. - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 0 - 1 - - - - - - - @@ -378,9 +413,6 @@ QGroupBox::title { Segoe UI - - advmode - QGroupBox,QGroupBox::title { border: none; @@ -405,7 +437,7 @@ QGroupBox::title { 0 - + Segoe UI @@ -486,7 +518,7 @@ QGroupBox::title { - + Segoe UI @@ -585,149 +617,6 @@ QGroupBox::title { - - - - 0 - 0 - 481 - 26 - - - - - true - - - &Program - - - - - - - - - - - - - &Help - - - - - - - - - Display Toolbar - - - false - - - false - - - TopToolBarArea - - - false - - - - - - - - - - - false - - - - :/MainWindow/img/writetqfp.png:/MainWindow/img/writetqfp.png - - - Erase/Program/Verify Device - - - - - false - - - - :/MainWindow/img/erasetqfp.png:/MainWindow/img/erasetqfp.png - - - Erase Device - - - false - - - - - - :/MainWindow/img/help.png:/MainWindow/img/help.png - - - &About - - - - - false - - - - :/MainWindow/img/verify.png:/MainWindow/img/verify.png - - - &Verify Device - - - false - - - - - false - - - &Settings... - - - - - false - - - - :/MainWindow/img/Reset.png:/MainWindow/img/Reset.png - - - Reset Device - - - - - false - - - - :/MainWindow/img/BlankCheck.png:/MainWindow/img/BlankCheck.png - - - Blank Check - - - false - - diff --git a/qt5_src/Bootloader/main.cpp b/qt5_src/Bootloader/main.cpp index 70b6a11..b0d3a12 100644 --- a/qt5_src/Bootloader/main.cpp +++ b/qt5_src/Bootloader/main.cpp @@ -30,7 +30,6 @@ #include #include "MainWindow.h" -#include int main(int argc, char *argv[]) { @@ -41,10 +40,6 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationDomain("source.jojcorp.com"); QCoreApplication::setApplicationName("Dancepad Interface FW Flash Tool"); - QFontDatabase::addApplicationFont(":/fonts/IBMPlexSans-Regular.ttf"); - QFontDatabase::addApplicationFont(":/fonts/IBMPlexSans-Medium.ttf"); - QFontDatabase::addApplicationFont(":/fonts/IBMPlexSans-Light.ttf"); - MainWindow w; w.show(); return a.exec(); diff --git a/qt5_src/Bootloader/resources.qrc b/qt5_src/Bootloader/resources.qrc index 992d560..399435c 100644 --- a/qt5_src/Bootloader/resources.qrc +++ b/qt5_src/Bootloader/resources.qrc @@ -11,9 +11,4 @@ img/help.png img/Microchip_logo.Ico - - IBMPlexSans-Regular.ttf - IBMPlexSans-Medium.ttf - IBMPlexSans-Light.ttf - diff --git a/qt5_src/version.h b/qt5_src/version.h index bf3f00f..296d85f 100644 --- a/qt5_src/version.h +++ b/qt5_src/version.h @@ -1,3 +1 @@ - -#define APPLICATION "USB Bootloader" #define VERSION "2.15"