闫刚 qgroundcontrol地面站QML界面中固件升级功能架构

1. px4设备固件升级-简介部分

qgroundcontrol地面站升级px4设备是从qml到cpulsplus到串口协议等,1个复杂的软件架构。下面分2部分讲解,
一部分是qml部分,另一部分是cpp实现部分.

2. px4设备固件升级-qml部分

2.1 qml的调用关系

MainWindowHybrid.qml
 -> MainWindowInner.qml
  -> SetupView.qml
   -> FirmwareUpgrade.qml
int main(int argc, char *argv[])
    -> static MainWindow::create();
      ->  _mainQmlWidgetHolder = qgcApp()->toolbox()->corePlugin()->createMainQmlWidgetHolder(_centralLayout, this);
         ->QGCQmlWidgetHolder* pMainQmlWidgetHolder = new QGCQmlWidgetHolder(QString(), nullptr, parent);
         ->pMainQmlWidgetHolder->setSource(QUrl::fromUserInput("qrc:qml/MainWindowHybrid.qml")); 

MainWindowHybrid.qml


Loader {
        id:             mainWindowInner
        anchors.fill:   parent
        source:         "MainWindowInner.qml"
        Connections {
            target: mainWindowInner.item
            onReallyClose: controller.reallyClose()
        }
    }

MainWindowInner.qml

Rectangle {
    id:     setupView
    color:  qgcPal.window


    readonly property string _setupViewSource:      "SetupView.qml"

SetupView.qml


    function showFirmwarePanel()
    {
        if (!ScreenTools.isMobile) {
            panelLoader.setSource("FirmwareUpgrade.qml")
        }
    }

  SubMenuButton {
                id:                 firmwareButton
                imageResource:      "/qmlimages/FirmwareUpgradeIcon.png"
                setupIndicator:     false
                exclusiveGroup:     setupButtonGroup
                visible:            !ScreenTools.isMobile && _corePlugin.options.showFirmwareUpgrade
                text:               qsTr("Firmware")
                Layout.fillWidth:   true

                onClicked: showFirmwarePanel()
            }

FirmwareUpgrade.qml

   FirmwareUpgradeController {
                id:             controller
                progressBar:    progressBar
                statusLog:      statusTextArea

                property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle

                Component.onCompleted: {
                    controllerCompleted = true
                    if (qgcView.completedSignalled) {
                        // We can only start the board search when the Qml and Controller are completely done loading
                        controller.startBoardSearch()
                    }
                }

2.2 将FirmwareUpgradeController注册到qml中

void QGCApplication::_initCommon(void)
 -> qmlRegisterType<FirmwareUpgradeController>      (kQGCControllers,                       1, 0, "FirmwareUpgradeController");

2.3 声明接口供qml调用

Q_INVOKABLE void startBoardSearch(void);
    
    /// Cancels whatever state the upgrade worker thread is in
    Q_INVOKABLE void cancel(void);
    
    /// Called when the firmware type has been selected by the user to continue the flash process.
    Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
                           FirmwareType_t firmwareType = StableFirmware,
                           FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );

    /// Called to flash when upgrade is running in singleFirmwareMode
    Q_INVOKABLE void flashSingleFirmwareMode(FirmwareType_t firmwareType);

    Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromVersionIndex(int index);

2.4 js部分

FirmwareUpgradeController是1个类名字,id是controller就可以和
controller.startBoardSearch()
controller.flash(stack, firmwareType, vehicleType)

3. px4设备固件升级-cpp部分

3个对象,FirmwareUpgradeController这个最顶层控制升级的,
PX4FirmwareUpgradeThreadController是控制px4升级线程的,
PX4FirmwareUpgradeThreadWorker升级过程是1个线程执行的

3.1 对象之间的关系

FirmwareUpgradeController::FirmwareUpgradeController(void)
_threadController = new PX4FirmwareUpgradeThreadController(this);
_worker = new PX4FirmwareUpgradeThreadWorker(this); 

3.2 分析升级flash

PX4FirmwareUpgradeThreadWorker::_flash是1个槽函数,操函数的连接在
下面,_controller发出的信号是_flashOnThread,通过找代码PX4FirmwareUpgradeThreadController::flash发出的_flashOnThread信号

3.3 查询板子

 controller.startBoardSearch() 
   -> FirmwareUpgradeController::startBoardSearch(void)
       -> linkMgr->disconnectAll();
       -> PX4FirmwareUpgradeThreadController::startFindBoardLoop(void);
           ->  emit _startFindBoardLoopOnThread();
              -> connect(_controller, &PX4FirmwareUpgradeThreadController::_startFindBoardLoopOnThread,  
                  this, &PX4FirmwareUpgradeThreadWorker::_startFindBoardLoop);
                  -> PX4FirmwareUpgradeThreadWorker::_startFindBoardLoop
                    -> PX4FirmwareUpgradeThreadWorker::_findBoardOnce
                      -> PX4FirmwareUpgradeThreadWorker::_findBootloader
                        ->  _bootloaderPort = new QSerialPort();
                        -> if (_bootloader->open(_bootloaderPort, portInfo.systemLocation())) {
                        -> if (_bootloader->sync(_bootloaderPort)) {
                              -> if (_sendCommand(port, PROTO_GET_SYNC)) {
                                 ->  if (!_write(port, buf, 2)) {
                                 ->  if (!_getCommandResponse(port, responseTimeout)) {
                                      -> if (!_read(port, response, 2, responseTimeout)) {
                                           -> bytesRead = port->read((char*)&data[bytesAlreadyRead], maxSize);

3.4 进行flash烧写固件

controller.flash(stack, firmwareType, vehicleType)
  -> _FirmwareUpgradeController::flash(AutoPilotStackType_t stackType,FirmwareType_t,FirmwareVehicleType_t)
     ->  _getFirmwareFile(firmwareId);
       ->  _downloadFirmware();
          -> QGCFileDownload* downloader = new QGCFileDownload(this);
             connect(downloader, &QGCFileDownload::downloadFinished, this, &FirmwareUpgradeController::_firmwareDownloadFinished);
             -> void FirmwareUpgradeController::_firmwareDownloadFinished(QString remoteFile, QString localFile)
                -> FirmwareImage* image = new FirmwareImage(this);
                -> _threadController->flash(image);
                        ->void PX4FirmwareUpgradeThreadController::flash(const FirmwareImage* image)
                            ->connect(_controller, &PX4FirmwareUpgradeThreadController::_flashOnThread,               this, &PX4FirmwareUpgradeThreadWorker::_flash);
                            -> PX4FirmwareUpgradeThreadWorker::_flash()
                            if (_erase()) {
                                if (_bootloader->program(_bootloaderPort, _controller->image())) {
                                 emit _reboot();
                                 emit flashComplete();

3.5 分析bootloader对象的_read函数

Bootloader::_read是最核心的代码

  • 打开1个定时器
    QTime timeout;
    timeout.start();

  • 直接判断elasped时间
    if (timeout.elapsed() > readTimeout) {

  • 等待数据
    port->waitForReadyRead(100);

  • 直接读数据
    bytesRead = port->read((char*)&data[bytesAlreadyRead], maxSize);


bool Bootloader::_read(QSerialPort* port, uint8_t* data, qint64 maxSize, int readTimeout)
{
    qint64 bytesAlreadyRead = 0;
    
    while (bytesAlreadyRead < maxSize) {

        //1. 打开1个定时器
        QTime timeout;
        timeout.start();

        
        while (port->bytesAvailable() < 1) {
           
            if (timeout.elapsed() > readTimeout) {
                _errorString = tr("Timeout waiting for bytes to be available");
                return false;
            }
            //3. 等待100ms
            port->waitForReadyRead(100);
        }
        // 4. 直接读数据
        qint64 bytesRead;
        bytesRead = port->read((char*)&data[bytesAlreadyRead], maxSize);
        
        if (bytesRead == -1) {
            _errorString = tr("Read failed: error: %1").arg(port->errorString());
            return false;
        } else {
            Q_ASSERT(bytesRead != 0);
            bytesAlreadyRead += bytesRead;
        }
    }
    
    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值