You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
7.5 KiB
166 lines
7.5 KiB
/*===================================================================== |
|
|
|
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 Bootloader Utility routines |
|
/// @author Don Gagne <don@thegagnes.com> |
|
|
|
#ifndef PX4Bootloader_H |
|
#define PX4Bootloader_H |
|
|
|
#include "qextserialport.h" |
|
|
|
#include <stdint.h> |
|
|
|
/// @brief This class is used to communicate with the Bootloader. |
|
class PX4Bootloader : public QObject |
|
{ |
|
Q_OBJECT |
|
|
|
public: |
|
explicit PX4Bootloader(QObject *parent = 0); |
|
|
|
/// @brief Returns the error message associated with the last failed call to one of the bootloader |
|
/// utility routine below. |
|
QString errorString(void) { return _errorString; } |
|
|
|
/// @brief Write a byte to the port |
|
/// @param port Port to write to |
|
/// @param data Bytes to write |
|
/// @param maxSize Number of bytes to write |
|
/// @return true: success |
|
bool write(QextSerialPort* port, const uint8_t* data, qint64 maxSize); |
|
bool write(QextSerialPort* port, const uint8_t byte); |
|
|
|
/// @brief Read a set of bytes from the port |
|
/// @param data Read bytes into this buffer |
|
/// @param maxSize Number of bytes to read |
|
/// @param readTimeout Msecs to wait for bytes to become available on port |
|
bool read(QextSerialPort* port, uint8_t* data, qint64 maxSize, int readTimeout = _readTimout); |
|
|
|
/// @brief Read a PROTO_SYNC command response from the bootloader |
|
/// @param responseTimeout Msecs to wait for response bytes to become available on port |
|
bool getCommandResponse(QextSerialPort* port, const int responseTimeout = _responseTimeout); |
|
|
|
/// @brief Send a PROTO_GET_DEVICE command to retrieve a value from the bootloader |
|
/// @param param Value to retrieve using INFO_BOARD_* enums |
|
/// @param value Returned value |
|
bool getBoardInfo(QextSerialPort* port, uint8_t param, uint32_t& value); |
|
|
|
/// @brief Send a command to the bootloader |
|
/// @param cmd Command to send using PROTO_* enums |
|
/// @return true: Command sent and valid sync response returned |
|
bool sendCommand(QextSerialPort* port, uint8_t cmd, int responseTimeout = _responseTimeout); |
|
|
|
/// @brief Program the board with the specified firmware |
|
bool program(QextSerialPort* port, const QString& firmwareFilename); |
|
|
|
/// @brief Verify the board flash. How it works depend on bootloader rev |
|
/// Rev 2: Read the flash back and compare it against the firmware file |
|
/// Rev 3: Compare CRCs for flash and file |
|
bool verify(QextSerialPort* port, const QString firmwareFilename); |
|
|
|
/// @brief Read a PROTO_SYNC response from the bootloader |
|
/// @return true: Valid sync response was received |
|
bool sync(QextSerialPort* port); |
|
|
|
/// @brief Retrieve a set of board info from the bootloader |
|
/// @param bootloaderVersion Returned INFO_BL_REV |
|
/// @param boardID Returned INFO_BOARD_ID |
|
/// @param flashSize Returned INFO_FLASH_SIZE |
|
bool getBoardInfo(QextSerialPort* port, uint32_t& bootloaderVersion, uint32_t& boardID, uint32_t& flashSize); |
|
|
|
/// @brief Opens a port to the bootloader |
|
bool open(QextSerialPort* port, const QString portName); |
|
|
|
/// @brief Sends a PROTO_REBOOT command to the bootloader |
|
bool sendBootloaderReboot(QextSerialPort* port); |
|
|
|
/// @brief Sends a PROTO_ERASE command to the bootlader |
|
bool erase(QextSerialPort* port); |
|
|
|
signals: |
|
/// @brief Signals progress indicator for long running bootloader utility routines |
|
void updateProgramProgress(int curr, int total); |
|
|
|
private: |
|
enum { |
|
// protocol bytes |
|
PROTO_INSYNC = 0x12, ///< 'in sync' byte sent before status |
|
PROTO_EOC = 0x20, ///< end of command |
|
|
|
// Reply bytes |
|
PROTO_OK = 0x10, ///< INSYNC/OK - 'ok' response |
|
PROTO_FAILED = 0x11, ///< INSYNC/FAILED - 'fail' response |
|
PROTO_INVALID = 0x13, ///< INSYNC/INVALID - 'invalid' response for bad commands |
|
|
|
// Command bytes |
|
PROTO_GET_SYNC = 0x21, ///< NOP for re-establishing sync |
|
PROTO_GET_DEVICE = 0x22, ///< get device ID bytes |
|
PROTO_CHIP_ERASE = 0x23, ///< erase program area and reset program address |
|
PROTO_PROG_MULTI = 0x27, ///< write bytes at program address and increment |
|
PROTO_GET_CRC = 0x29, ///< compute & return a CRC |
|
PROTO_BOOT = 0x30, ///< boot the application |
|
|
|
// Command bytes - Rev 2 boootloader only |
|
PROTO_CHIP_VERIFY = 0x24, ///< begin verify mode |
|
PROTO_READ_MULTI = 0x28, ///< read bytes at programm address and increment |
|
|
|
INFO_BL_REV = 1, ///< bootloader protocol revision |
|
BL_REV_MIN = 2, ///< Minimum supported bootlader protocol |
|
BL_REV_MAX = 4, ///< Maximum supported bootloader protocol |
|
INFO_BOARD_ID = 2, ///< board type |
|
INFO_BOARD_REV = 3, ///< board revision |
|
INFO_FLASH_SIZE = 4, ///< max firmware size in bytes |
|
|
|
PROG_MULTI_MAX = 32, ///< write size for PROTO_PROG_MULTI, must be multiple of 4 |
|
READ_MULTI_MAX = 32 ///< read size for PROTO_READ_MULTI, must be multiple of 4 |
|
}; |
|
|
|
bool _findBootloader(void); |
|
bool _downloadFirmware(void); |
|
bool _bootloaderVerifyRev2(QextSerialPort* port, const QString firmwareFilename); |
|
bool _bootloaderVerifyRev3(QextSerialPort* port); |
|
|
|
static const int _boardIDPX4FMUV1 = 5; ///< Board ID for PX4 V1 board |
|
static const int _boardIDPX4FMUV2 = 9; ///< Board ID for PX4 V2 board |
|
static const int _boardIDPX4Flow = 6; ///< Board ID for PX4 Floaw board |
|
static const int _boardIDuNode = 29; ///< Board ID for uNode board |
|
|
|
uint32_t _boardID; ///< board id for currently connected board |
|
uint32_t _boardFlashSize; ///< flash size for currently connected board |
|
uint32_t _imageCRC; ///< CRC for image in currently selected firmware file |
|
uint32_t _bootloaderVersion; ///< Bootloader version |
|
|
|
QString _firmwareFilename; ///< Currently selected firmware file to flash |
|
|
|
QString _errorString; ///< Last error |
|
|
|
static const int _eraseTimeout = 20000; ///< Msecs to wait for response from erase command |
|
static const int _rebootTimeout = 10000; ///< Msecs to wait for reboot command to cause serial port to disconnect |
|
static const int _verifyTimeout = 5000; ///< Msecs to wait for response to PROTO_GET_CRC command |
|
static const int _readTimout = 2000; ///< Msecs to wait for read bytes to become avilable |
|
static const int _responseTimeout = 2000; ///< Msecs to wait for command response bytes |
|
}; |
|
|
|
#endif // PX4FirmwareUpgrade_H
|
|
|