QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
PX4FirmwareUpgradeThread.cc
Go to the documentation of this file.
2#include "Bootloader.h"
3#include "FirmwareImage.h"
5
6#include <QtCore/QThread>
7#include <QtCore/QTimer>
8
10 : _controller(controller)
11{
12 connect(_controller, &PX4FirmwareUpgradeThreadController::_initThreadWorker, this, &PX4FirmwareUpgradeThreadWorker::_init);
13 connect(_controller, &PX4FirmwareUpgradeThreadController::_startFindBoardLoopOnThread, this, &PX4FirmwareUpgradeThreadWorker::_startFindBoardLoop);
14 connect(_controller, &PX4FirmwareUpgradeThreadController::_flashOnThread, this, &PX4FirmwareUpgradeThreadWorker::_flash);
15 connect(_controller, &PX4FirmwareUpgradeThreadController::_rebootOnThread, this, &PX4FirmwareUpgradeThreadWorker::_reboot);
16 connect(_controller, &PX4FirmwareUpgradeThreadController::_cancel, this, &PX4FirmwareUpgradeThreadWorker::_cancel);
17}
18
23
24void PX4FirmwareUpgradeThreadWorker::_init(void)
25{
26 // We create the timers here so that they are on the right thread
27
28 _findBoardTimer = new QTimer(this);
29 _findBoardTimer->setSingleShot(true);
30 _findBoardTimer->setInterval(500);
31 connect(_findBoardTimer, &QTimer::timeout, this, &PX4FirmwareUpgradeThreadWorker::_findBoardOnce);
32}
33
34void PX4FirmwareUpgradeThreadWorker::_cancel(void)
35{
36 qCDebug(FirmwareUpgradeVerboseLog) << "_cancel";
37 if (_bootloader) {
38 _bootloader->reboot();
39 _bootloader->close();
40 _bootloader->deleteLater();
41 _bootloader = nullptr;
42 }
43}
44
45void PX4FirmwareUpgradeThreadWorker::_startFindBoardLoop(void)
46{
47 _foundBoard = false;
48 _findBoardFirstAttempt = true;
49 _findBoardOnce();
50}
51
52void PX4FirmwareUpgradeThreadWorker::_findBoardOnce(void)
53{
54 qCDebug(FirmwareUpgradeVerboseLog) << "_findBoardOnce";
55
56 QGCSerialPortInfo portInfo;
58 QString boardName;
59
60 if (_findBoardFromPorts(portInfo, boardType, boardName)) {
61 if (!_foundBoard) {
62 _foundBoard = true;
63 _foundBoardPortInfo = portInfo;
64 emit foundBoard(_findBoardFirstAttempt, portInfo, boardType, boardName);
65 if (!_findBoardFirstAttempt) {
66
67 _bootloader = new Bootloader(boardType == QGCSerialPortInfo::BoardTypeSiKRadio, this);
68 connect(_bootloader, &Bootloader::updateProgress, this, &PX4FirmwareUpgradeThreadWorker::_updateProgress);
69
70 if (_bootloader->open(portInfo.portName())) {
71 uint32_t bootloaderVersion;
72 uint32_t boardId;
73 uint32_t flashSize;
74 if (_bootloader->getBoardInfo(bootloaderVersion, boardId, flashSize)) {
75 emit foundBoardInfo(bootloaderVersion, boardId, flashSize);
76 } else {
77 emit error(_bootloader->errorString());
78 }
79 } else {
80 emit error(_bootloader->errorString());
81 }
82 return;
83 }
84 }
85 } else {
86 if (_foundBoard) {
87 _foundBoard = false;
88 qCDebug(FirmwareUpgradeLog) << "Board gone";
89 emit boardGone();
90 } else if (_findBoardFirstAttempt) {
91 emit noBoardFound();
92 }
93 }
94
95 _findBoardFirstAttempt = false;
96 _findBoardTimer->start();
97}
98
99bool PX4FirmwareUpgradeThreadWorker::_findBoardFromPorts(QGCSerialPortInfo& portInfo, QGCSerialPortInfo::BoardType_t& boardType, QString& boardName)
100{
101 for (const QGCSerialPortInfo& info: QGCSerialPortInfo::availablePorts()) {
102 info.getBoardInfo(boardType, boardName);
103
104 qCDebug(FirmwareUpgradeVerboseLog) << "Serial Port --------------";
105 qCDebug(FirmwareUpgradeVerboseLog) << "\tboard type" << boardType;
106 qCDebug(FirmwareUpgradeVerboseLog) << "\tboard name" << boardName;
107 qCDebug(FirmwareUpgradeVerboseLog) << "\tmanufacturer:" << info.manufacturer();
108 qCDebug(FirmwareUpgradeVerboseLog) << "\tport name:" << info.portName();
109 qCDebug(FirmwareUpgradeVerboseLog) << "\tdescription:" << info.description();
110 qCDebug(FirmwareUpgradeVerboseLog) << "\tsystem location:" << info.systemLocation();
111 qCDebug(FirmwareUpgradeVerboseLog) << "\tvendor ID:" << info.vendorIdentifier();
112 qCDebug(FirmwareUpgradeVerboseLog) << "\tproduct ID:" << info.productIdentifier();
113
114 if (info.canFlash()) {
115 portInfo = info;
116 return true;
117 }
118 }
119
120 return false;
121}
122
123void PX4FirmwareUpgradeThreadWorker::_reboot(void)
124{
125 _bootloader->reboot();
126}
127
128void PX4FirmwareUpgradeThreadWorker::_flash(void)
129{
130 qCDebug(FirmwareUpgradeLog) << "PX4FirmwareUpgradeThreadWorker::_flash";
131
132 if (!_bootloader->initFlashSequence()) {
133 emit error(_bootloader->errorString());
134 return;
135 }
136
137 if (_erase()) {
138 emit status(tr("Programming new version..."));
139
140 if (_bootloader->program(_controller->image())) {
141 qCDebug(FirmwareUpgradeLog) << "Program complete";
142 emit status("Program complete");
143 } else {
144 qCDebug(FirmwareUpgradeLog) << "Program failed:" << _bootloader->errorString();
145 goto Error;
146 }
147
148 emit status(tr("Verifying program..."));
149
150 if (_bootloader->verify(_controller->image())) {
151 qCDebug(FirmwareUpgradeLog) << "Verify complete";
152 emit status(tr("Verify complete"));
153 } else {
154 qCDebug(FirmwareUpgradeLog) << "Verify failed:" << _bootloader->errorString();
155 goto Error;
156 }
157 }
158
159 emit status(tr("Rebooting board"));
160 _reboot();
161
162 _bootloader->close();
163 _bootloader->deleteLater();
164 _bootloader = nullptr;
165
166 emit flashComplete();
167
168 return;
169
170Error:
171 emit error(_bootloader->errorString());
172 _reboot();
173 _bootloader->close();
174 _bootloader->deleteLater();
175 _bootloader = nullptr;
176}
177
178bool PX4FirmwareUpgradeThreadWorker::_erase(void)
179{
180 qCDebug(FirmwareUpgradeLog) << "PX4FirmwareUpgradeThreadWorker::_erase";
181
182 emit eraseStarted();
183 emit status(tr("Erasing previous program..."));
184
185 if (_bootloader->erase()) {
186 qCDebug(FirmwareUpgradeLog) << "Erase complete";
187 emit status(tr("Erase complete"));
188 emit eraseComplete();
189 return true;
190 } else {
191 qCDebug(FirmwareUpgradeLog) << "Erase failed:" << _bootloader->errorString();
192 emit error(_bootloader->errorString());
193 return false;
194 }
195}
196
198 QObject(parent)
199{
200 _worker = new PX4FirmwareUpgradeThreadWorker(this);
201 _workerThread = new QThread(this);
202 _worker->moveToThread(_workerThread);
203
204 connect(_worker, &PX4FirmwareUpgradeThreadWorker::updateProgress, this, &PX4FirmwareUpgradeThreadController::_updateProgress);
205 connect(_worker, &PX4FirmwareUpgradeThreadWorker::foundBoard, this, &PX4FirmwareUpgradeThreadController::_foundBoard);
206 connect(_worker, &PX4FirmwareUpgradeThreadWorker::noBoardFound, this, &PX4FirmwareUpgradeThreadController::_noBoardFound);
207 connect(_worker, &PX4FirmwareUpgradeThreadWorker::boardGone, this, &PX4FirmwareUpgradeThreadController::_boardGone);
208 connect(_worker, &PX4FirmwareUpgradeThreadWorker::foundBoardInfo, this, &PX4FirmwareUpgradeThreadController::_foundBoardInfo);
209 connect(_worker, &PX4FirmwareUpgradeThreadWorker::error, this, &PX4FirmwareUpgradeThreadController::_error);
210 connect(_worker, &PX4FirmwareUpgradeThreadWorker::status, this, &PX4FirmwareUpgradeThreadController::_status);
211 connect(_worker, &PX4FirmwareUpgradeThreadWorker::eraseStarted, this, &PX4FirmwareUpgradeThreadController::_eraseStarted);
212 connect(_worker, &PX4FirmwareUpgradeThreadWorker::eraseComplete, this, &PX4FirmwareUpgradeThreadController::_eraseComplete);
213 connect(_worker, &PX4FirmwareUpgradeThreadWorker::flashComplete, this, &PX4FirmwareUpgradeThreadController::_flashComplete);
214
215 _workerThread->start();
216
217 emit _initThreadWorker();
218}
219
221{
222 _workerThread->quit();
223 _workerThread->wait();
224
225 delete _workerThread;
226}
227
229{
230 qCDebug(FirmwareUpgradeLog) << "PX4FirmwareUpgradeThreadController::findBoard";
232}
233
235{
236 qCDebug(FirmwareUpgradeLog) << "PX4FirmwareUpgradeThreadController::cancel";
237 emit _cancel();
238}
239
241{
242 _image = image;
243 emit _flashOnThread();
244}
Error error
Bootloader Utility routines. Works with PX4 and 3DR Radio bootloaders.
Definition Bootloader.h:19
bool program(const FirmwareImage *image)
void updateProgress(int curr, int total)
Signals progress indicator for long running bootloader utility routines.
QString errorString(void)
Definition Bootloader.h:25
bool erase(void)
bool reboot(void)
bool initFlashSequence(void)
bool open(const QString portName)
Definition Bootloader.cc:21
bool verify(const FirmwareImage *image)
bool getBoardInfo(uint32_t &bootloaderVersion, uint32_t &boardID, uint32_t &flashSize)
Definition Bootloader.cc:68
void close(void)
Definition Bootloader.h:28
Support for Intel Hex firmware file.
Provides methods to interact with the bootloader. The commands themselves are signalled across to PX4...
PX4FirmwareUpgradeThreadController(QObject *parent=nullptr)
void startFindBoardLoop(void)
Begins the process of searching for a supported board connected to any serial port....
void flash(const FirmwareImage *image)
Used to run bootloader commands on a separate thread. These routines are mainly meant to to be called...
void foundBoard(bool firstAttempt, const QGCSerialPortInfo &portInfo, int type, QString boardName)
void error(const QString &errorString)
void foundBoardInfo(int bootloaderVersion, int boardID, int flashSize)
void status(const QString &statusText)
PX4FirmwareUpgradeThreadWorker(PX4FirmwareUpgradeThreadController *controller)
void updateProgress(int curr, int total)
QString portName() const
Error
Error codes for decompression operations.