PX4FirmwareUpgradeThread.h 7.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009, 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

/// @file
///     @brief PX4 Firmware Upgrade operations which occur on a seperate thread.
///     @author Don Gagne <don@thegagnes.com>

#ifndef PX4FirmwareUpgradeThread_H
#define PX4FirmwareUpgradeThread_H

#include <QObject>
#include <QSerialPort>
#include <QThread>
#include <QTimer>
#include <QTime>

#include <stdint.h>

#include "PX4Bootloader.h"

/// @brief Used to run bootloader commands on a seperate thread. These routines are mainly meant to to be called
///         internally by the PX4FirmwareUpgradeThreadController. Clients should call the various public methods
///         exposed by PX4FirmwareUpgradeThreadController.
class PX4FirmwareUpgradeThreadWorker : public QObject
{
    Q_OBJECT
    
public:
    PX4FirmwareUpgradeThreadWorker(QObject* parent = NULL);
    ~PX4FirmwareUpgradeThreadWorker();
    
    enum {
        commandBootloader,
        commandProgram,
        commandVerify,
        commandErase,
        commandCancel
    };
    
public slots:
    void init(void);
    void findBoard(int msecTimeout);
    void findBootloader(const QString portName, int msecTimeout);
    void timeout(void);
    void cancelFind(void);
    void sendBootloaderReboot(void);
    void program(const QString firmwareFilename);
    void verify(const QString firmwareFilename);
    void erase(void);
    
signals:
    void foundBoard(const QString portname, QString portDescription);
    void foundBootloader(int bootloaderVersion, int boardID, int flashSize);
    void bootloaderSyncFailed(void);
    void error(const int command, const QString errorString);
    void complete(const int command);
    void findTimeout(void);
    void updateProgress(int curr, int total);
    
private slots:
    void _findBoardOnce(void);
    void _findBootloaderOnce(void);
    void _updateProgramProgress(int curr, int total) { emit updateProgress(curr, total); }
    void _closeFind(void);
    
private:
    PX4Bootloader*      _bootloader;
    QSerialPort*        _bootloaderPort;
    QTimer*             _timerTimeout;
    QTimer*             _timerRetry;
    QTime               _elapsed;
    QString             _portName;
    static const int    _retryTimeout = 1000;
};

/// @brief Provides methods to interact with the bootloader. The commands themselves are signalled
///         across to PX4FirmwareUpgradeThreadWorker so that they run on the seperate thread.
class PX4FirmwareUpgradeThreadController : public QObject
{
    Q_OBJECT
    
public:
    PX4FirmwareUpgradeThreadController(QObject* parent = NULL);
    ~PX4FirmwareUpgradeThreadController(void);
    
    /// @brief Begins the process of searching for a PX4 board connected to any serial port.
    ///     @param msecTimeout Numbers of msecs to continue looking for a board to become available.
    void findBoard(int msecTimeout);
    
    /// @brief Begins the process of attempting to communicate with the bootloader on the specified port.
    ///     @param portName Name of port to attempt a bootloader connection on.
    ///     @param msecTimeout Number of msecs to continue to wait for a bootloader to appear on the port.
    void findBootloader(const QString& portName, int msecTimeout);
    
    /// @brief Cancel an in progress findBoard or FindBootloader
    void cancelFind(void) { emit _cancelFindOnThread(); }
    
    /// @brief Sends a reboot command to the bootloader
    void sendBootloaderReboot(void) { emit _sendBootloaderRebootOnThread(); }
    
    /// @brief Flash the specified firmware onto the board
    void program(const QString firmwareFilename) { emit _programOnThread(firmwareFilename); }
    
    /// @brief Verify the board flash with respect to the specified firmware image
    void verify(const QString firmwareFilename) { emit _verifyOnThread(firmwareFilename); }
    
    /// @brief Send and erase command to the bootloader
    void erase(void) { emit _eraseOnThread(); }

signals:
    /// @brief Emitted by the findBoard process when it finds the board.
    ///     @param portName Port that board is on
    ///     @param portDescription User friendly port description
    void foundBoard(const QString portname, QString portDescription);
    
    /// @brief Emitted by the findBootloader process when has a connection to the bootloader
    void foundBootloader(int bootloaderVersion, int boardID, int flashSize);
    
    /// @brief Emitted by the bootloader commands when an error occurs.
    ///     @param errorCommand Command which caused the error, using PX4FirmwareUpgradeThreadWorker command* enum values
    void error(const int errorCommand, const QString errorString);
    
    /// @brief Signalled when the findBootloader process connects to the port, but cannot sync to the
    ///         bootloader.
    void bootloaderSyncFailed(void);
    
    /// @brief Signalled when the findBoard or findBootloader process times out before success
    void findTimeout(void);
    
    /// @brief Signalled by the bootloader commands other than find* that they have complete successfully.
    ///     @param command Command which completed, using PX4FirmwareUpgradeThreadWorker command* enum values
    void complete(const int command);
    
    /// @brief Signalled to update progress for long running bootloader commands
    void updateProgress(int curr, int total);
    
    void _initThreadWorker(void);
    void _findBoardOnThread(int msecTimeout);
    void _findBootloaderOnThread(const QString& portName, int msecTimeout);
    void _sendBootloaderRebootOnThread(void);
    void _programOnThread(const QString firmwareFilename);
    void _verifyOnThread(const QString firmwareFilename);
    void _eraseOnThread(void);
    void _cancelFindOnThread(void);
    
private slots:
    void _foundBoard(const QString portname, QString portDescription);
    void _foundBootloader(int bootloaderVersion, int boardID, int flashSize);
    void _bootloaderSyncFailed(void);
    void _error(const int errorCommand, const QString errorString) { emit error(errorCommand, errorString); }
    void _complete(const int command) { emit complete(command); }
    void _findTimeout(void);
    void _updateProgress(int curr, int total) { emit updateProgress(curr, total); }
    
private:
    PX4FirmwareUpgradeThreadWorker* _worker;
    QThread*                        _workerThread;  ///< Thread which PX4FirmwareUpgradeThreadWorker runs on
};

#endif