加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
mainwindow.cpp 19.59 KB
一键复制 编辑 原始数据 按行查看 历史
yuyaowen 提交于 2022-08-10 10:43 . first commit
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "launch.h"
#include <QSettings>
#include <QFileDialog>
#include <QStandardPaths>
#include <QTextCodec>
#include <QMessageBox>
#include <QLabel>
#include <QCryptographicHash>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->statusBar->addPermanentWidget(new QLabel("Ver:"+QString(__DATE__ "_" __TIME__)));
ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color: #10ff10; width: 20px;}");
// 获取配置文件中板子的名称,更新到ui
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup("Global");
factoryMode = configFile.value("factory").toBool();
QString lastBoard=configFile.value("last_selected_board").toString();
configFile.endGroup();
QStringList sections = configFile.childGroups();
foreach(QString item, sections)
{
if (item.endsWith("Board"))
{
configFile.beginGroup(item);
QString boardName = configFile.value("NAME").toString();
configFile.endGroup();
ui->boardComboBox->addItem(boardName);
}
}
if (!lastBoard.isEmpty())
{
ui->boardComboBox->setCurrentText(lastBoard);
}
/* 生成update flag文件 */
QFile needUpdateFlag(firmwareDir + curNeedUpdateFlag);
needUpdateFlag.open(QIODevice::WriteOnly | QIODevice::Truncate);
QDataStream out(&needUpdateFlag);
out << static_cast<qint64>(0xffffffffb66bb66b);
needUpdateFlag.close();
QFile updateFlag(firmwareDir + curUpdateFlag);
updateFlag.open(QIODevice::WriteOnly | QIODevice::Truncate);
QDataStream out1(&updateFlag);
out1 << static_cast<qint64>(0xc77cc77cb66bb66b);
updateFlag.close();
ui->imageLabel->setHidden(true);
if (factoryMode) // 工厂模式
{
/* 不该显示的按钮藏起来 */
ui->burnIFlashPushButton->setHidden(true);
ui->burnEFlashPushButton->setHidden(true);
ui->eraseIFlashPushButton->setHidden(true);
ui->eraseEFlashPushButton->setHidden(true);
/* 修改刷机按钮样式 */
ui->burnAllPushButton->setFixedSize(522, 34);
ui->burnAllPushButton->setText("烧写程序");
/* 用图片盖住各选项 */
ui->imageLabel->raise();
ui->imageLabel->setHidden(false);
Launch la;
la.exec();
ui->boardComboBox->setCurrentText(la.getBoardName());
}
}
MainWindow::~MainWindow()
{
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup("Global");
configFile.setValue("last_selected_board", ui->boardComboBox->currentText());
configFile.endGroup();
QFile(firmwareDir + defaultBkpPara).remove();
QFile(firmwareDir + curUpdateFlag).remove();
QFile(firmwareDir + curNeedUpdateFlag).remove();
delete ui;
}
QString MainWindow::findSectionByName(const QString &boardName)
{
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
QStringList sections = configFile.childGroups();
foreach (QString item, sections)
{
configFile.beginGroup(item);
if (configFile.value("NAME").toString() == boardName)
{
configFile.endGroup();
return item;
}
configFile.endGroup();
}
return nullptr;
}
QString MainWindow::findKeyByValue(const QString &section, const QString &value)
{
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup(section);
QStringList keyList = configFile.allKeys();
foreach(QString key, keyList)
{
if (configFile.value(key).toString() == value)
{
return key;
}
}
configFile.endGroup();
return nullptr;
}
int MainWindow::burnExternFlash(QString filePath, QString loaderPath, QString offset)
{
QStringList param;
param.append("-P");
param.append(filePath);
param.append(offset);
param.append("-V");
param.append("after_programming");
param.append("-EL");
param.append(loaderPath);
param.append("-Rst");
param.append("-Q");
cliProcessInternal.start(stlinkPath, param);
cliProcessInternal.waitForStarted();
cliProcessInternal.waitForFinished(15000);
return judgeConnectionError(cliProcessInternal.readAll());
}
int MainWindow::eraseExternFlash(QString loaderPath)
{
QStringList param;
param.append("-c");
param.append("SWD");
param.append("UR");
param.append("-ME");
param.append("-EL");
param.append(loaderPath);
param.append("-Rst");
param.append("-Q");
cliProcessInternal.start(stlinkPath, param);
cliProcessInternal.waitForStarted();
cliProcessInternal.waitForFinished(15000);
return judgeConnectionError(cliProcessInternal.readAll());
}
int MainWindow::burnInternalFlash(QString filePath, QString offset)
{
QStringList param;
param.append("-c");
param.append("SWD");
param.append("UR");
param.append("-P");
param.append(filePath);
param.append(offset);
param.append("-V");
param.append("after_programming");
param.append("-Rst");
param.append("-Q");
cliProcessInternal.start(stlinkPath, param);
cliProcessInternal.waitForStarted();
cliProcessInternal.waitForFinished(15000);
return judgeConnectionError(cliProcessInternal.readAll());
}
int MainWindow::eraseInternalFlash()
{
QStringList param;
param.append("-c");
param.append("SWD");
param.append("UR");
param.append("-ME");
param.append("-Rst");
param.append("-Q");
cliProcessInternal.start(stlinkPath, param);
cliProcessInternal.waitForStarted();
cliProcessInternal.waitForFinished(15000);
return judgeConnectionError(cliProcessInternal.readAll());
}
int MainWindow::judgeConnectionError(QString res)
{
int ret;
if (res.contains("MCU Reset") &&
(res.contains("Programming Complete") ||
res.contains("Flash memory erased") ||
res.contains("External Memory full erase")))
{
ret = 0;
}
else if (res.contains("No target connected"))
{
QMessageBox::critical(this, "USB错误", "请检查ST-Link到PCB之间的连接线。\r\n或者重新拔插ST-Link的USB再试一次。");
ret = -1;
}
else if (res.contains("No ST-LINK detected") || res.contains("Unable to connect to ST-LINK"))
{
QMessageBox::critical(this, "SWD错误", "请检查电脑到ST-Link之间的连接线。");
ret = -2;
}
else if (res.contains("Timeout during flash programming") || res.contains("External Memory full erase"))
{
QMessageBox::critical(this, "超时", "芯片选择有误。");
ret = -3;
}
else if (res.contains("Unable to open file"))
{
QMessageBox::critical(this, "文件错误", "固件文件丢失,或者配置文件不对。");
ret = -3;
}
else
{
QMessageBox::critical(this, "未知错误", res);
ret = -100;
}
if (ret != 0)
{
ui->progressBar->setValue(0);
}
return ret;
}
qint64 MainWindow::convertQIntEndian(qint64 src)
{
qint64 dest = 0;
for (int i = 0; i < 8; i++) {
dest <<= 8;
dest |= src & 0xff;
src >>= 8;
}
return dest;
}
qint32 MainWindow::convertQIntEndian(qint32 src)
{
qint32 dest = 0;
for (int i = 0; i < 4; i++) {
dest <<= 8;
dest |= src & 0xff;
src >>= 8;
}
return dest;
}
void MainWindow::on_boardComboBox_currentTextChanged(const QString &arg1)
{
ui->socComboBox->clear();
setWindowTitle("厨芯:" + arg1);
curSection = findSectionByName(arg1);
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup(curSection);
QStringList keyList = configFile.allKeys();
foreach(QString key, keyList)
{
if (key.contains("SOC"))
{
ui->socComboBox->addItem(configFile.value(key).toString());
}
}
/* 显示电路板图片,只有工厂模式才会显示,否则隐藏 */
QString boardImage = configFile.value("IMG").toString();
ui->imageLabel->setPixmap(QPixmap(boardImagePath + boardImage).scaled(ui->imageLabel->size()));
/* 显示烧写计数 */
unsigned int burnCount = configFile.value("BURN_COUNT").toUInt();
ui->countLabel->setText("已成功烧写:" + QString::number(burnCount));
/* 显示板子注释信息 */
ui->commitLabel->setText(configFile.value("COMMIT").toString());
configFile.endGroup();
}
void MainWindow::on_socComboBox_currentTextChanged(const QString &arg1)
{
ui->bootComboBox->clear();
ui->appComboBox->clear();
ui->extLoaderLabel->clear();
curSoc = arg1;
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup(curSection);
QStringList keyList = configFile.allKeys();
foreach(QString key, keyList)
{
if (key.startsWith(curSoc + "_BL"))
{
ui->bootComboBox->addItem(configFile.value(key).toString());
ui->bootCheckBox->setChecked(true);
}
if (key.startsWith(curSoc + "_APP"))
{
ui->appComboBox->addItem(configFile.value(key).toString());
ui->appCheckBox->setChecked(true);
}
if (key.startsWith(curSoc + "_EXLOADER"))
{
curExtLoader = configFile.value(key).toString();
ui->extLoaderLabel->setText("SPI-Flash: " + curExtLoader);
}
}
configFile.endGroup();
}
void MainWindow::on_burnAllPushButton_clicked()
{
int ret;
QString pathStr;
ui->statusBar->showMessage("准备烧录,请稍后...", 3000);
ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color: #c0c0ff; width: 20px;}"); // 设置进度条颜色
ui->progressBar->setValue(1);
if (ui->bootCheckBox->isChecked())
{
ui->statusBar->showMessage("正在烧写片内Flash:BootLoader(1/6)", 3000);
if (curBoot.contains(":/"))
{
pathStr = curBoot;
}
else
{
pathStr = firmwareDir + curBoot;
}
ret = burnInternalFlash(pathStr, defaultIFlashBootOffset);
if (ret != 0)
{
return;
}
}
ui->progressBar->setValue(10);
if (ui->appCheckBox->isChecked())
{
ui->statusBar->showMessage("正在烧写片内Flash:Application(2/6)", 3000);
if (curApp.contains(":/"))
{
pathStr = curApp;
}
else
{
pathStr = firmwareDir + curApp;
}
ret = burnInternalFlash(pathStr, defaultIFlashAppOffset);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(36);
ui->statusBar->showMessage("正在烧写片外Flash升级标识区(3/6)", 3000);
if (curUpdateFlag.contains(":/"))
{
pathStr = curUpdateFlag;
}
else
{
pathStr = firmwareDir + curUpdateFlag;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashUpdateFlagOffset);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(41);
ui->statusBar->showMessage("正在烧写片外Flash待升级标识区(4/6)", 3000);
if (curNeedUpdateFlag.contains(":/"))
{
pathStr = curNeedUpdateFlag;
}
else
{
pathStr = firmwareDir + curNeedUpdateFlag;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashNeedUpdateFlagOffset);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(59);
ui->statusBar->showMessage("正在烧写片外Flash备份固件参数区(5/6)", 3000);
if (curBkpPara.contains(":/"))
{
pathStr = curBkpPara;
}
else
{
pathStr = firmwareDir + curBkpPara;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashBkpParaOffset);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(78);
ui->statusBar->showMessage("正在烧写片外Flash备份固件区(6/6)", 3000);
if (curApp.contains(":/"))
{
pathStr = curApp;
}
else
{
pathStr = firmwareDir + curApp;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashAppOffset);
if (ret != 0)
{
return;
}
}
ui->progressBar->setValue(100);
ui->statusBar->showMessage("烧录完成。", 5000);
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup(curSection);
unsigned int count = configFile.value("BURN_COUNT").toUInt();
count++;
configFile.setValue("BURN_COUNT", count);
configFile.endGroup();
ui->countLabel->setText("已成功烧写:" + QString::number(count));
ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color: #a0ffa0; width: 20px;}");
// QMessageBox::information(this, "成功", "烧录成功!");
// ui->progressBar->setValue(0);
}
void MainWindow::on_burnIFlashPushButton_clicked()
{
int ret;
QString pathStr;
ui->statusBar->showMessage("正在烧写片内Flash...", 3000);
ui->progressBar->setValue(1);
if (ui->bootCheckBox->isChecked())
{
ui->statusBar->showMessage("正在烧写片内Flash:BootLoader", 3000);
if (curBoot.contains(":/"))
{
pathStr = curBoot;
}
else
{
pathStr = firmwareDir + curBoot;
}
ret = burnInternalFlash(pathStr, defaultIFlashBootOffset);
if (ret != 0)
{
return;
}
}
ui->progressBar->setValue(49);
if (ui->appCheckBox->isChecked())
{
ui->statusBar->showMessage("正在烧写片内Flash:Application", 3000);
if (curApp.contains(":/"))
{
pathStr = curApp;
}
else
{
pathStr = firmwareDir + curApp;
}
ret = burnInternalFlash(pathStr, defaultIFlashAppOffset);
if (ret != 0)
{
return;
}
}
ui->progressBar->setValue(100);
ui->statusBar->showMessage("片内Flash烧录完成。", 5000);
}
void MainWindow::on_burnEFlashPushButton_clicked()
{
int ret;
QString pathStr;
if (curApp.isEmpty())
{
ui->progressBar->setValue(0);
ui->statusBar->showMessage("没有应用程序文件可烧写!", 3000);
return;
}
ui->statusBar->showMessage("正在烧写片外Flash升级标识区(1/4)", 3000);
ui->progressBar->setValue(1);
if (curUpdateFlag.contains(":/"))
{
pathStr = curUpdateFlag;
}
else
{
pathStr = firmwareDir + curUpdateFlag;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashUpdateFlagOffset);
if (ret != 0)
{
return;
}
ui->statusBar->showMessage("正在烧写片外Flash待升级标识区(2/4)", 3000);
ui->progressBar->setValue(23);
if (curNeedUpdateFlag.contains(":/"))
{
pathStr = curNeedUpdateFlag;
}
else
{
pathStr = firmwareDir + curNeedUpdateFlag;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashNeedUpdateFlagOffset);
if (ret != 0)
{
return;
}
ui->statusBar->showMessage("正在烧写片外Flash备份固件参数区(3/4)", 3000);
ui->progressBar->setValue(47);
if (curBkpPara.contains(":/"))
{
pathStr = curBkpPara;
}
else
{
pathStr = firmwareDir + curBkpPara;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashBkpParaOffset);
if (ret != 0)
{
return;
}
ui->statusBar->showMessage("正在烧写片外Flash备份固件区(4/4)", 3000);
ui->progressBar->setValue(68);
if (curApp.contains(":/"))
{
pathStr = curApp;
}
else
{
pathStr = firmwareDir + curApp;
}
ret = burnExternFlash(pathStr, extLoaderDir + curExtLoader, defaultExtFlashAppOffset);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(100);
ui->statusBar->showMessage("片外Flash烧录完成。", 5000);
}
void MainWindow::on_eraseIFlashPushButton_clicked()
{
int ret;
ui->statusBar->showMessage("正在擦除片内Flash", 1000);
ui->progressBar->setValue(87);
ret = eraseInternalFlash();
if (ret != 0)
{
return;
}
ui->progressBar->setValue(100);
ui->statusBar->showMessage("擦除片内Flash完成", 5000);
}
void MainWindow::on_eraseEFlashPushButton_clicked()
{
int ret;
ui->statusBar->showMessage("正在擦除片外Flash,大约需要12秒", 12000);
ui->progressBar->setValue(15);
ret = eraseExternFlash(extLoaderDir + curExtLoader);
if (ret != 0)
{
return;
}
ui->progressBar->setValue(100);
ui->statusBar->showMessage("擦除片外Flash完成", 5000);
}
void MainWindow::on_bootComboBox_currentTextChanged(const QString &arg1)
{
curBoot = arg1;
if (curBoot.isEmpty())
ui->bootCheckBox->setChecked(false);
}
void MainWindow::on_appComboBox_currentTextChanged(const QString &arg1)
{
curApp = arg1;
if (curApp.isEmpty())
ui->appCheckBox->setChecked(false);
curBkpPara = defaultBkpPara;
QString filePath;
if (curApp.contains(":/"))
{
filePath = curApp;
}
else {
filePath = firmwareDir + curApp;
}
QFile binFile(filePath);
if (binFile.open(QIODevice::ReadOnly))
{
QByteArray binData = QCryptographicHash::hash(binFile.readAll(), QCryptographicHash::Md5);
binFile.close();
QFile args(firmwareDir + defaultBkpPara);
args.open(QIODevice::WriteOnly | QIODevice::Truncate);
QDataStream out(&args);
out << static_cast<qint32>(0);
out << convertQIntEndian(static_cast<qint32>(binFile.size()));
args.write(binData.toHex());
args.close();
}
ui->firmwareLabel->setText(curApp);
}
void MainWindow::on_openBootPushButton_clicked()
{
QString fileName;
fileName = QFileDialog::getOpenFileName(this, tr("Open file"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("BootLoader(*.hex *.bin)"));
if (!fileName.isEmpty()) {
ui->bootComboBox->setCurrentText(fileName);
ui->bootCheckBox->setChecked(true);
}
}
void MainWindow::on_openAppPushButton_clicked()
{
QString fileName;
fileName = QFileDialog::getOpenFileName(this, tr("Open file"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), tr("Application(*.hex *.bin)"));
if (!fileName.isEmpty()) {
ui->appComboBox->setCurrentText(fileName);
ui->appCheckBox->setChecked(true);
}
}
void MainWindow::on_clearCountPushButton_clicked()
{
unsigned int count = 0;
QSettings configFile(configFilePath, QSettings::IniFormat);
configFile.setIniCodec(QTextCodec::codecForName("UTF-8"));
configFile.beginGroup(curSection);
configFile.setValue("BURN_COUNT", count);
configFile.endGroup();
ui->countLabel->setText("已成功烧写:" + QString::number(count));
ui->progressBar->setValue(0);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化