且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Qt flash_eraseall nandwrite 进度条显示擦除、烧录

更新时间:2022-08-12 20:24:13

/*****************************************************************************
 *              Qt flash_eraseall nandwrite 进度条显示擦除、烧录
 * 声明:
 *   当我们在 Linux shell中执行nand擦除、烧入程序时,我们可以通过终端查看
 * 过程,但是有时候我们可能希望能够有个界面,这样会更直观的提供当前的程序
 * 的执行状态,于是个人写了这个Demo,目前暂时使用。
 * 
 *                                   2015-10-7 雨 深圳 南山平山村 曾剑锋
 ****************************************************************************/

|\\\\\\\\-*- 目录 -*-/////// | 一、cat main.cpp | 二、cat mainwindow.h | 三、cat mainwindow.cpp | 四、cat thread.h | 五、cat thread.cpp \\\\\\\\\\\\\\///////////// 一、cat main.cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); /** * 窗口最大化,不允许最小化 */ MainWindow w; w.setWindowFlags(w.windowFlags()& ~Qt::WindowMaximizeButtonHint& ~Qt::WindowMinimizeButtonHint); w.showMaximized(); w.show(); return a.exec(); } 二、cat mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "thread.h" /** * shell command: * nandwrite -p /dev/mtd7 ubi.img * ...... * Writing data to block 724 at offset 0x5a80000 * Writing data to block 725 at offset 0x5aa0000 * Writing data to block 726 at offset 0x5ac0000 * Writing data to block 727 at offset 0x5ae0000 * Writing data to block 728 at offset 0x5b00000 * Writing data to block 729 at offset 0x5b20000 * Writing data to block 730 at offset 0x5b40000 * * 这个值要设置得相对大一点比较好,这样就不会出现比100%还大得情况 */ #define NANDWRITEBLOCKCOUNTS 740 namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected: void moveEvent(QMoveEvent *); void resizeEvent(QResizeEvent *); void closeEvent(QCloseEvent *); public slots: /** * 与线程对应的三个信号处理函数 */ void dealNandEraseMesg(QString string); void dealNandWriteMesg(QString string); void dealTitleMesg(QString string); private: Ui::MainWindow *ui; Thread *thread; }; #endif // MAINWINDOW_H 三、cat mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QProcess> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); /** * 创建线程来处理nand的擦除、写入,主要是避免在MainWindow的UI线程中处理事务, * 这样可以避免UI界面不能及时显示改变的数据界面,这在Android的开发中也会 * 遇到这种情况,类似的处理方式。 */ thread = new Thread(); connect(thread, SIGNAL(nandEraserMesg(QString)), this, SLOT(dealNandEraseMesg(QString))); connect(thread, SIGNAL(titleMesg(QString)), this, SLOT(dealTitleMesg(QString))); connect(thread, SIGNAL(nandWriteMesg(QString)), this, SLOT(dealNandWriteMesg(QString))); thread->start(); } void MainWindow::dealNandEraseMesg(QString string) { ui->progressBar->setValue(string.toInt()); } void MainWindow::dealNandWriteMesg(QString string) { int rate = string.toInt()*100/NANDWRITEBLOCKCOUNTS; /** * 由于最后为了确保显示了100,我传了1000过来这个远大于NANDWRITEBLOCKCOUNTS的值 * 所以这里需要这样操作来避免显示大于100的值 */ rate = rate >= 100 ? 100 : rate; ui->progressBar->setValue(rate); } void MainWindow::dealTitleMesg(QString string) { ui->title->setText(string); } MainWindow::~MainWindow() { delete ui; } void MainWindow::moveEvent(QMoveEvent *) { /** * 防止窗口被移动 */ this->move(QPoint(0,0)); } void MainWindow::resizeEvent(QResizeEvent *) { this->showMaximized(); } void MainWindow::closeEvent(QCloseEvent *) { exit(0); } 四、cat thread.h #ifndef THREAD_H #define THREAD_H #include <QThread> #include <QProcess> #include <QDebug> class Thread : public QThread { Q_OBJECT public: explicit Thread(QObject *parent = 0); signals: /** * 数据处理过程中,需要用到的三个信号 */ void titleMesg(QString string); void nandEraserMesg(QString string); void nandWriteMesg(QString string); public slots: void run(); /** * 判断字符串是不是数字组成的: * 返回值: * 0:表示是纯数字组成的; * 1:表示不是纯数字组成的。 */ int isDigitStr(QString src); }; #endif // THREAD_H 五、cat thread.cpp #include "thread.h" #include <stdio.h> #include <unistd.h> #include <QByteArray> #include <QStringList> Thread::Thread(QObject *parent) : QThread(parent) { } /** * 重写的run()方法 */ void Thread::run() { QString readBuffer; /** * 擦除的时候使用QProcess来处理 */ QProcess process; process.start("flash_eraseall /dev/mtd7"); process.waitForFinished(-1); // will wait forever until finished /** * 显示正在做的事 */ emit titleMesg("erase rootfs..."); while ( !process.atEnd() ) { // 没有到数据末尾 if ( process.canReadLine() ) { // 有数据可读 readBuffer = process.readLine(512); // 读取数据 /** * Erasing 128 Kibyte @ ca40000 -- 81 % complet" * Erasing 128 Kibyte" e560000 -- 92 % complete * " asing 128 Kibyte @ e980000 -- 93 % complete * Erasing 128 Kibyte @ eae0000 -- 94 % comp" te * Erasing 128 Kibyt" @ f040000 -- 96 % complete * Erasing 128 Kibyte @ f460000 -- 98 % complete " * * 以下代码主要是为了获取上面输出中的百分比数值 */ // 正则表达式分割数据 QStringList currentLine = readBuffer.split(QRegExp("[\\s]+")); if ( currentLine.length() > 7 ) { // 我们需要第六个字段 // 第六个字段是否是由纯数字组成 if ( !isDigitStr( currentLine[6]) ) { // 将数据发送给UI线程去处理 emit nandEraserMesg(currentLine[6]); //qDebug() << readBuffer; } } } } emit nandEraserMesg(QString(100)); // 擦除数据完毕 /** * 1. shell命令行下执行 nandwrite -p /dev/mtd7 ubi.img 的输出: * Writing data to block 47 at offset 0x5e0000 * Writing data to block 48 at offset 0x600000 * Writing data to block 49 at offset 0x620000 * Writing data to block 50 at offset 0x640000 * Writing data to block 51 at offset 0x660000 * 2. 在编码测试过程中发现使用QProcess无法获取到nandwrite执行过程中的数据, * 仅仅在处理完毕的时候才会收到数据,所以处理效果不好; * 3. 所以改用popen来做这件事,但是popen也仅仅是比QProcess好那么一点,每次 * 都是以12%的梯度增长,虽然还是没有像shell中运行的效果,但目前勉强还 * 是能用,所以这里也就暂时这么做; * 4. 目前没找到更好的办法在解决这个事情。 */ char buff[64]; FILE *fp = popen("nandwrite -p /dev/mtd7 ubi.img", "r"); int count = 0; emit titleMesg("update rootfs..."); while (!feof(fp)) { fgets(buff, 64, fp ); emit nandWriteMesg(QString::number(count++)); } pclose(fp); // 这里仅仅是为了保证processor bar一定显示100%才这么做的,没其他的意思 emit nandWriteMesg("1000"); // 显示更新完毕 emit titleMesg("rootfs update over."); } int Thread::isDigitStr(QString src) { //QString 转换为 char* QByteArray ba = src.toLatin1(); const char *s = ba.data(); /** * 字符的二进制值是否在'0'、'9'之间 */ while(*s && *s>='0' && *s<='9') s++; if (*s) { //不是纯数字 return -1; } else { //纯数字 return 0; } }