Newer
Older
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
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
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef Bootloader_H
#define Bootloader_H
#include "FirmwareImage.h"
#include "qextserialport.h"
#include <stdint.h>
/// Bootloader Utility routines. Works with PX4 bootloader and 3DR Radio bootloader.
class Bootloader : public QObject
{
Q_OBJECT
public:
explicit Bootloader(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 Opens a port to the bootloader
bool open(QextSerialPort* port, const QString portName);
/// @brief Read a PROTO_SYNC response from the bootloader
/// @return true: Valid sync response was received
bool sync(QextSerialPort* port);
/// @brief Erases the current program
bool erase(QextSerialPort* port);
/// @brief Program the board with the specified image
bool program(QextSerialPort* port, const FirmwareImage* image);
/// @brief Verify the board flash.
bool verify(QextSerialPort* port, const FirmwareImage* image);
/// @brief Retrieve a set of board info from the bootloader of PX4 FMU and PX4 Flow boards
/// @param bootloaderVersion Returned INFO_BL_REV
/// @param boardID Returned INFO_BOARD_ID
/// @param flashSize Returned INFO_FLASH_SIZE
bool getPX4BoardInfo(QextSerialPort* port, uint32_t& bootloaderVersion, uint32_t& boardID, uint32_t& flashSize);
/// @brief Retrieve the board id from a 3DR Radio
bool get3DRRadioBoardId(QextSerialPort* port, uint32_t& boardID);
/// @brief Sends a PROTO_REBOOT command to the bootloader
bool reboot(QextSerialPort* port);
// Supported bootloader board ids
static const int boardIDPX4FMUV1 = 5; ///< PX4 V1 board
static const int boardIDPX4FMUV2 = 9; ///< PX4 V2 board
static const int boardIDPX4FMUV4 = 11; ///< PX4 V4 board
static const int boardIDPX4Flow = 6; ///< PX4 Flow board
static const int boardIDAeroCore = 98; ///< Gumstix AeroCore board
static const int boardID3DRRadio = 78; ///< 3DR Radio
static const int boardIDMINDPXFMUV2 = 88; ///< MindPX V2 board
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
signals:
/// @brief Signals progress indicator for long running bootloader utility routines
void updateProgress(int curr, int total);
private:
bool _binProgram(QextSerialPort* port, const FirmwareImage* image);
bool _ihxProgram(QextSerialPort* port, const FirmwareImage* image);
bool _write(QextSerialPort* port, const uint8_t* data, qint64 maxSize);
bool _write(QextSerialPort* port, const uint8_t byte);
bool _read(QextSerialPort* port, uint8_t* data, qint64 maxSize, int readTimeout = _readTimout);
bool _sendCommand(QextSerialPort* port, uint8_t cmd, int responseTimeout = _responseTimeout);
bool _getCommandResponse(QextSerialPort* port, const int responseTimeout = _responseTimeout);
bool _getPX4BoardInfo(QextSerialPort* port, uint8_t param, uint32_t& value);
bool _verifyBytes(QextSerialPort* port, const FirmwareImage* image);
bool _binVerifyBytes(QextSerialPort* port, const FirmwareImage* image);
bool _ihxVerifyBytes(QextSerialPort* port, const FirmwareImage* image);
bool _verifyCRC(QextSerialPort* port);
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_LOAD_ADDRESS = 0x24, ///< set next programming 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 = 5, ///< 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 = 64, ///< write size for PROTO_PROG_MULTI, must be multiple of 4
READ_MULTI_MAX = 0x28 ///< read size for PROTO_READ_MULTI, must be multiple of 4. Sik Radio max size is 0x28
};
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 available