Browse Source

Merge pull request #7319 from DonLakeFlyer/ChibiOSBootloader

Full ChibiOS bootloader support, plus autoconnect for ChibiOS builds
QGC4.4
Don Gagne 6 years ago committed by GitHub
parent
commit
47d1f9f98c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      ChangeLog.md
  2. 2
      src/AutoPilotPlugins/Common/SetupPage.qml
  3. 13
      src/Vehicle/Vehicle.cc
  4. 4
      src/Vehicle/Vehicle.h
  5. 2
      src/VehicleSetup/Bootloader.h
  6. 39
      src/VehicleSetup/FirmwareUpgrade.qml
  7. 111
      src/VehicleSetup/FirmwareUpgradeController.cc
  8. 1
      src/VehicleSetup/PX4FirmwareUpgradeThread.cc
  9. 94
      src/comm/QGCSerialPortInfo.cc
  10. 8
      src/comm/QGCSerialPortInfo.h
  11. 19
      src/comm/USBBoardInfo.json

3
ChangeLog.md

@ -6,12 +6,11 @@ Note: This file only contains high level features or important fixes.
### 3.6.0 - Daily Build ### 3.6.0 - Daily Build
* Improved support for flashing/connecting to ChibiOS bootloaders boards.
* Making the camera API available to all firmwares, not just PX4. * Making the camera API available to all firmwares, not just PX4.
* ArduPilot: Support configurable mavlink stream rates. Available from Settings/Mavlink page. * ArduPilot: Support configurable mavlink stream rates. Available from Settings/Mavlink page.
* Major rewrite and bug fix pass through Structure Scan. Previous version had such bad problems that it can no longer be supported. Plans with Structure Scan will need to be recreated. New QGC will not load old Structure Scan plans. * Major rewrite and bug fix pass through Structure Scan. Previous version had such bad problems that it can no longer be supported. Plans with Structure Scan will need to be recreated. New QGC will not load old Structure Scan plans.
* Major rewrite and bug fix pass through Structure Scan. Previous version had such bad problems that it can no longer be supported. Plans with Structure Scan will need to be recreated. New QGC will not load old Structure Scan plans.
### 3.5.1 - Not yet released ### 3.5.1 - Not yet released
* Fix tile set count but in OfflineMaps which would cause image and elevation tile set to have incorrect counts and be incorrectly marked as download incomplete. * Fix tile set count but in OfflineMaps which would cause image and elevation tile set to have incorrect counts and be incorrectly marked as download incomplete.

2
src/AutoPilotPlugins/Common/SetupPage.qml

@ -86,7 +86,7 @@ QGCView {
anchors.right: parent.right anchors.right: parent.right
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: pageDescription text: pageDescription
visible: !ScreenTools.isShortScreen visible: pageDescription !== "" && !ScreenTools.isShortScreen
} }
} }
} }

13
src/Vehicle/Vehicle.cc

@ -3849,6 +3849,19 @@ int Vehicle::versionCompare(int major, int minor, int patch)
return _firmwarePlugin->versionCompare(this, major, minor, patch); return _firmwarePlugin->versionCompare(this, major, minor, patch);
} }
#if !defined(NO_ARDUPILOT_DIALECT)
void Vehicle::flashBootloader(void)
{
sendMavCommand(defaultComponentId(),
MAV_CMD_FLASH_BOOTLOADER,
true, // show error
0, 0, 0, 0, // param 1-4 not used
290876); // magic number
}
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

4
src/Vehicle/Vehicle.h

@ -756,6 +756,10 @@ public:
/// @param percent 0-no power, 100-full power /// @param percent 0-no power, 100-full power
Q_INVOKABLE void motorTest(int motor, int percent); Q_INVOKABLE void motorTest(int motor, int percent);
#if !defined(NO_ARDUPILOT_DIALECT)
Q_INVOKABLE void flashBootloader(void);
#endif
bool guidedModeSupported (void) const; bool guidedModeSupported (void) const;
bool pauseVehicleSupported (void) const; bool pauseVehicleSupported (void) const;
bool orbitModeSupported (void) const; bool orbitModeSupported (void) const;

2
src/VehicleSetup/Bootloader.h

@ -64,7 +64,7 @@ public:
static const int boardIDPX4FMUV1 = 5; ///< PX4 V1 board, as from USB PID static const int boardIDPX4FMUV1 = 5; ///< PX4 V1 board, as from USB PID
static const int boardIDPX4FMUV2 = 9; ///< PX4 V2 board, as from USB PID static const int boardIDPX4FMUV2 = 9; ///< PX4 V2 board, as from USB PID
static const int boardIDPX4FMUV4 = 11; ///< PX4 V4 board, as from USB PID static const int boardIDPX4FMUV4 = 11; ///< PX4 V4 board, as from USB PID
static const int boardIDPX4FMUV4PRO = 13; ///< PX4 V4PRO board, as from USB PID static const int boardIDPX4FMUV4PRO = 13; ///< PX4 V4PRO board, as from USB PID
static const int boardIDPX4FMUV5 = 50; ///< PX4 V5 board, as from USB PID static const int boardIDPX4FMUV5 = 50; ///< PX4 V5 board, as from USB PID
static const int boardIDPX4Flow = 6; ///< PX4 Flow board, as from USB PID static const int boardIDPX4Flow = 6; ///< PX4 Flow board, as from USB PID
static const int boardIDAeroCore = 98; ///< Gumstix AeroCore board, as from USB PID static const int boardIDAeroCore = 98; ///< Gumstix AeroCore board, as from USB PID

39
src/VehicleSetup/FirmwareUpgrade.qml

@ -23,9 +23,14 @@ import QGroundControl.Controllers 1.0
import QGroundControl.ScreenTools 1.0 import QGroundControl.ScreenTools 1.0
SetupPage { SetupPage {
id: firmwarePage id: firmwarePage
pageComponent: firmwarePageComponent pageComponent: firmwarePageComponent
pageName: "Firmware" // For building setup page title: 'Firmware Setup' pageName: qsTr("Firmware")
showAdvanced: _activeVehicle && _activeVehicle.apmFirmware
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
signal cancelDialog
Component { Component {
id: firmwarePageComponent id: firmwarePageComponent
@ -40,7 +45,7 @@ SetupPage {
// a better way to hightlight them, or use less highlights. // a better way to hightlight them, or use less highlights.
// User visible strings // User visible strings
readonly property string title: "Firmware Setup" // Popup dialog title readonly property string title: qsTr("Firmware Setup") // Popup dialog title
readonly property string highlightPrefix: "<font color=\"" + qgcPal.warningText + "\">" readonly property string highlightPrefix: "<font color=\"" + qgcPal.warningText + "\">"
readonly property string highlightSuffix: "</font>" readonly property string highlightSuffix: "</font>"
@ -124,8 +129,8 @@ SetupPage {
} }
onError: { onError: {
hideDialog()
statusTextArea.append(flashFailText) statusTextArea.append(flashFailText)
firmwarePage.cancelDialog()
} }
} }
@ -165,7 +170,11 @@ SetupPage {
px4FlightStackRadio2.text = qsTr("PX4 Flight Stack ") + versionString px4FlightStackRadio2.text = qsTr("PX4 Flight Stack ") + versionString
} }
Component.onCompleted: updatePX4VersionDisplay() Component.onCompleted: {
firmwarePage.advanced = false
firmwarePage.showAdvanced = false
updatePX4VersionDisplay()
}
function accept() { function accept() {
hideDialog() hideDialog()
@ -195,6 +204,12 @@ SetupPage {
cancelFlash() cancelFlash()
} }
Connections {
target: firmwarePage
onCancelDialog: reject()
}
ExclusiveGroup { ExclusiveGroup {
id: firmwareGroup id: firmwareGroup
} }
@ -438,8 +453,16 @@ SetupPage {
} }
ProgressBar { ProgressBar {
id: progressBar id: progressBar
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
visible: !flashBootloaderButton.visible
}
QGCButton {
id: flashBootloaderButton
text: qsTr("Flash ChibiOS Bootloader")
visible: firmwarePage.advanced
onClicked: _activeVehicle.flashBootloader()
} }
TextArea { TextArea {

111
src/VehicleSetup/FirmwareUpgradeController.cc

@ -363,48 +363,44 @@ void FirmwareUpgradeController::_initFirmwareHash()
// PX4 Firmwares // PX4 Firmwares
for (const FirmwareType_t& firmwareType: px4MapFirmwareTypeToDir.keys()) { for (const FirmwareType_t& firmwareType: px4MapFirmwareTypeToDir.keys()) {
QString dir = px4MapFirmwareTypeToDir[firmwareType]; QString dir = px4MapFirmwareTypeToDir[firmwareType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v5")); _rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v5"));
_rgFMUV4PROFirmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v4pro")); _rgFMUV4PROFirmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v4pro"));
_rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v4")); _rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v4"));
_rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v3")); _rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v3"));
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v2")); _rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackPX4, firmwareType, DefaultVehicleFirmware), px4Url.arg(dir).arg("v2"));
} }
#if !defined(NO_ARDUPILOT_DIALECT) #if !defined(NO_ARDUPILOT_DIALECT)
// ArduPilot Firmwares // ArduPilot non-ChibiOS Firmwares for direct board id to fmu mappings
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) { for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType]; QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmMapVehicleTypeToDir.keys()) { for (const FirmwareVehicleType_t& vehicleType: apmMapVehicleTypeToDir.keys()) {
QString vehicleTypeDir = apmMapVehicleTypeToDir[vehicleType]; QString vehicleTypeDir = apmMapVehicleTypeToDir[vehicleType];
QString px4Dir = apmMapVehicleTypeToPX4Dir[vehicleType]; QString px4Dir = apmMapVehicleTypeToPX4Dir[vehicleType];
QString filename = apmMapVehicleTypeToFilename[vehicleType]; QString filename = apmMapVehicleTypeToFilename[vehicleType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("5")); _rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("5"));
_rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("4")); _rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("4"));
_rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("3")); _rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("3"));
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("2")); _rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg(px4Dir).arg(filename).arg("2"));
} }
} }
#endif
#if !defined(NO_ARDUPILOT_DIALECT) // ArduPilot ChibiOS Firmwares for direct board id to fmu mappings. Used when bootloader is not new ArduPilot bootloader.
// ArduPilot ChibiOS Firmwares when board id is is a known type. These are added directly into the various board type hashes.
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) { for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType]; QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) { for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) {
QString vehicleTypeDir = apmChibiOSMapVehicleTypeToDir[vehicleType]; QString vehicleTypeDir = apmChibiOSMapVehicleTypeToDir[vehicleType];
QString fmuDir = apmChibiOSMapVehicleTypeToFmuDir[vehicleType]; QString fmuDir = apmChibiOSMapVehicleTypeToFmuDir[vehicleType];
QString filename = apmChibiOSMapVehicleTypeToFilename[vehicleType]; QString filename = apmChibiOSMapVehicleTypeToFilename[vehicleType];
_rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("5").arg(fmuDir).arg(filename)); _rgFMUV5Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("5").arg(fmuDir).arg(filename));
_rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("4").arg(fmuDir).arg(filename)); _rgFMUV4Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("4").arg(fmuDir).arg(filename));
_rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("3").arg(fmuDir).arg(filename)); _rgFMUV3Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("3").arg(fmuDir).arg(filename));
_rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("2").arg(fmuDir).arg(filename)); _rgPX4FMUV2Firmware.insert (FirmwareIdentifier(AutoPilotStackAPM, firmwareType, vehicleType), apmChibiOSUrl.arg(vehicleTypeDir).arg(firmwareTypeDir).arg("2").arg(fmuDir).arg(filename));
} }
} }
#endif
#if !defined(NO_ARDUPILOT_DIALECT)
// ArduPilot ChibiOS Firmwares when board id is an unknown type but follows ArduPilot port info naming conventions. // ArduPilot ChibiOS Firmwares when board id is an unknown type but follows ArduPilot port info naming conventions.
// This is only used if the board using the ArduPilot port naming scheme. // This is only used if the board is using the new ArduPilot bootloader port naming scheme.
for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) { for (const FirmwareType_t& firmwareType: apmMapFirmwareTypeToDir.keys()) {
QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType]; QString firmwareTypeDir = apmMapFirmwareTypeToDir[firmwareType];
for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) { for (const FirmwareVehicleType_t& vehicleType: apmChibiOSMapVehicleTypeToDir.keys()) {
@ -487,85 +483,75 @@ void FirmwareUpgradeController::_bootloaderSyncFailed(void)
QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* FirmwareUpgradeController::_firmwareHashForBoardId(int boardId) QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* FirmwareUpgradeController::_firmwareHashForBoardId(int boardId)
{ {
QHash<FirmwareUpgradeController::FirmwareIdentifier, QString>* rgFirmware;
_rgFirmwareDynamic.clear();
switch (boardId) { switch (boardId) {
case Bootloader::boardIDPX4Flow: case Bootloader::boardIDPX4Flow:
rgFirmware = &_rgPX4FLowFirmware; _rgFirmwareDynamic = _rgPX4FLowFirmware;
break; break;
case Bootloader::boardIDPX4FMUV2: case Bootloader::boardIDPX4FMUV2:
rgFirmware = &_rgPX4FMUV2Firmware; _rgFirmwareDynamic = _rgPX4FMUV2Firmware;
break; break;
case Bootloader::boardIDPX4FMUV3: case Bootloader::boardIDPX4FMUV3:
rgFirmware = &_rgFMUV3Firmware; _rgFirmwareDynamic = _rgFMUV3Firmware;
break; break;
case Bootloader::boardIDPX4FMUV4: case Bootloader::boardIDPX4FMUV4:
rgFirmware = &_rgFMUV4Firmware; _rgFirmwareDynamic = _rgFMUV4Firmware;
break; break;
case Bootloader::boardIDPX4FMUV4PRO: case Bootloader::boardIDPX4FMUV4PRO:
rgFirmware = &_rgFMUV4PROFirmware; _rgFirmwareDynamic = _rgFMUV4PROFirmware;
break; break;
case Bootloader::boardIDPX4FMUV5: case Bootloader::boardIDPX4FMUV5:
rgFirmware = &_rgFMUV5Firmware; _rgFirmwareDynamic = _rgFMUV5Firmware;
break; break;
case Bootloader::boardIDAeroCore: case Bootloader::boardIDAeroCore:
rgFirmware = &_rgAeroCoreFirmware; _rgFirmwareDynamic = _rgAeroCoreFirmware;
break; break;
case Bootloader::boardIDAUAVX2_1: case Bootloader::boardIDAUAVX2_1:
rgFirmware = &_rgAUAVX2_1Firmware; _rgFirmwareDynamic = _rgAUAVX2_1Firmware;
break; break;
case Bootloader::boardIDMINDPXFMUV2: case Bootloader::boardIDMINDPXFMUV2:
rgFirmware = &_rgMindPXFMUV2Firmware; _rgFirmwareDynamic = _rgMindPXFMUV2Firmware;
break; break;
case Bootloader::boardIDTAPV1: case Bootloader::boardIDTAPV1:
rgFirmware = &_rgTAPV1Firmware; _rgFirmwareDynamic = _rgTAPV1Firmware;
break; break;
case Bootloader::boardIDASCV1: case Bootloader::boardIDASCV1:
rgFirmware = &_rgASCV1Firmware; _rgFirmwareDynamic = _rgASCV1Firmware;
break; break;
case Bootloader::boardIDCrazyflie2: case Bootloader::boardIDCrazyflie2:
rgFirmware = &_rgCrazyflie2Firmware; _rgFirmwareDynamic = _rgCrazyflie2Firmware;
break; break;
case Bootloader::boardIDOmnibusF4SD: case Bootloader::boardIDOmnibusF4SD:
rgFirmware = &_rgOmnibusF4SDFirmware; _rgFirmwareDynamic = _rgOmnibusF4SDFirmware;
break; break;
case Bootloader::boardIDNXPHliteV3: case Bootloader::boardIDNXPHliteV3:
rgFirmware = &_rgNXPHliteV3Firmware; _rgFirmwareDynamic = _rgNXPHliteV3Firmware;
break; break;
case Bootloader::boardID3DRRadio: case Bootloader::boardID3DRRadio:
rgFirmware = &_rg3DRRadioFirmware; _rgFirmwareDynamic = _rg3DRRadioFirmware;
break; break;
default: default:
rgFirmware = Q_NULLPTR; // Unknown board id
break;
} }
if (rgFirmware) { // Check for ArduPilot ChibiOS bootloader
_rgFirmwareDynamic = *rgFirmware; QStringList rgManufacturers = { QStringLiteral("ArduPilot"), QStringLiteral("Hex/ProfiCNC"), QStringLiteral("Holybro") };
} else { QString apmDescriptionSuffix("-BL");
_rgFirmwareDynamic.clear(); if (rgManufacturers.contains(_foundBoardInfo.manufacturer()) && _foundBoardInfo.description().endsWith(apmDescriptionSuffix)) {
} // Board ios using a ChibiOS bootloader. Prefer naming scheme from that over board ids for ArduPilot entries.
// Special case handling for ArduPilot named ChibiOS board // First remove the ChibiOS by board id entries from the list
if (_foundBoardInfo.manufacturer() == QStringLiteral("ArduPilot") || _foundBoardInfo.manufacturer() == QStringLiteral("Hex/ProfiCNC")) { for (const FirmwareIdentifier& firmwareId: _rgAPMChibiosReplaceNamedBoardFirmware.keys()) {
// Remove the ChibiOS by board id entries from the list _rgFirmwareDynamic.remove(firmwareId);
for (const FirmwareIdentifier& firmwareId: _rgFirmwareDynamic.keys()) {
switch (firmwareId.firmwareVehicleType) {
case CopterChibiOSFirmware:
case HeliChibiOSFirmware:
case PlaneChibiOSFirmware:
case RoverChibiOSFirmware:
case SubChibiOSFirmware:
_rgAPMChibiosReplaceNamedBoardFirmware.remove(firmwareId);
break;
default:
break;
}
} }
// Add the ChibiOS by board description entries to the list // Now add the ChibiOS by board description entries to the list
for (const FirmwareIdentifier& firmwareId: _rgAPMChibiosReplaceNamedBoardFirmware.keys()) { for (const FirmwareIdentifier& firmwareId: _rgAPMChibiosReplaceNamedBoardFirmware.keys()) {
QString namedUrl = _rgAPMChibiosReplaceNamedBoardFirmware[firmwareId]; QString namedUrl = _rgAPMChibiosReplaceNamedBoardFirmware[firmwareId];
_rgFirmwareDynamic.insert(firmwareId, namedUrl.replace(_apmBoardDescriptionReplaceText, _foundBoardInfo.description().left(_foundBoardInfo.description().length() - 3))); _rgFirmwareDynamic.insert(firmwareId, namedUrl.replace(_apmBoardDescriptionReplaceText, _foundBoardInfo.description().left(_foundBoardInfo.description().length() - apmDescriptionSuffix.length())));
} }
} }
@ -577,21 +563,16 @@ void FirmwareUpgradeController::_getFirmwareFile(FirmwareIdentifier firmwareId)
{ {
QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardId(static_cast<int>(_bootloaderBoardID)); QHash<FirmwareIdentifier, QString>* prgFirmware = _firmwareHashForBoardId(static_cast<int>(_bootloaderBoardID));
if (!prgFirmware && firmwareId.firmwareType != CustomFirmware) {
_errorCancel(tr("Attempting to flash an unknown board type, you must select 'Custom firmware file'"));
return;
}
if (firmwareId.firmwareType == CustomFirmware) { if (firmwareId.firmwareType == CustomFirmware) {
_firmwareFilename = QGCQFileDialog::getOpenFileName(nullptr, // Parent to main window _firmwareFilename = QGCQFileDialog::getOpenFileName(nullptr, // Parent to main window
tr("Select Firmware File"), // Dialog Caption tr("Select Firmware File"), // Dialog Caption
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), // Initial directory
tr("Firmware Files (*.px4 *.bin *.ihx)")); // File filter tr("Firmware Files (*.px4 *.apj *.bin *.ihx)")); // File filter
} else { } else {
if (prgFirmware->contains(firmwareId)) { if (prgFirmware->contains(firmwareId)) {
_firmwareFilename = prgFirmware->value(firmwareId); _firmwareFilename = prgFirmware->value(firmwareId);
} else { } else {
_errorCancel(tr("Unable to find specified firmware download location")); _errorCancel(tr("Unable to find specified firmware for board type"));
return; return;
} }
} }

1
src/VehicleSetup/PX4FirmwareUpgradeThread.cc

@ -125,6 +125,7 @@ bool PX4FirmwareUpgradeThreadWorker::_findBoardFromPorts(QGCSerialPortInfo& port
qCDebug(FirmwareUpgradeVerboseLog) << "Serial Port --------------"; qCDebug(FirmwareUpgradeVerboseLog) << "Serial Port --------------";
qCDebug(FirmwareUpgradeVerboseLog) << "\tboard type" << boardType; qCDebug(FirmwareUpgradeVerboseLog) << "\tboard type" << boardType;
qCDebug(FirmwareUpgradeVerboseLog) << "\tboard name" << boardName; qCDebug(FirmwareUpgradeVerboseLog) << "\tboard name" << boardName;
qCDebug(FirmwareUpgradeVerboseLog) << "\tmanufacturer:" << info.manufacturer();
qCDebug(FirmwareUpgradeVerboseLog) << "\tport name:" << info.portName(); qCDebug(FirmwareUpgradeVerboseLog) << "\tport name:" << info.portName();
qCDebug(FirmwareUpgradeVerboseLog) << "\tdescription:" << info.description(); qCDebug(FirmwareUpgradeVerboseLog) << "\tdescription:" << info.description();
qCDebug(FirmwareUpgradeVerboseLog) << "\tsystem location:" << info.systemLocation(); qCDebug(FirmwareUpgradeVerboseLog) << "\tsystem location:" << info.systemLocation();

94
src/comm/QGCSerialPortInfo.cc

@ -18,16 +18,17 @@
QGC_LOGGING_CATEGORY(QGCSerialPortInfoLog, "QGCSerialPortInfoLog") QGC_LOGGING_CATEGORY(QGCSerialPortInfoLog, "QGCSerialPortInfoLog")
bool QGCSerialPortInfo::_jsonLoaded = false; bool QGCSerialPortInfo::_jsonLoaded = false;
const char* QGCSerialPortInfo::_jsonFileTypeValue = "USBBoardInfo"; const char* QGCSerialPortInfo::_jsonFileTypeValue = "USBBoardInfo";
const char* QGCSerialPortInfo::_jsonBoardInfoKey = "boardInfo"; const char* QGCSerialPortInfo::_jsonBoardInfoKey = "boardInfo";
const char* QGCSerialPortInfo::_jsonBoardFallbackKey = "boardFallback"; const char* QGCSerialPortInfo::_jsonBoardDescriptionFallbackKey = "boardDescriptionFallback";
const char* QGCSerialPortInfo::_jsonVendorIDKey = "vendorID"; const char* QGCSerialPortInfo::_jsonBoardManufacturerFallbackKey = "boardManufacturerFallback";
const char* QGCSerialPortInfo::_jsonProductIDKey = "productID"; const char* QGCSerialPortInfo::_jsonVendorIDKey = "vendorID";
const char* QGCSerialPortInfo::_jsonBoardClassKey = "boardClass"; const char* QGCSerialPortInfo::_jsonProductIDKey = "productID";
const char* QGCSerialPortInfo::_jsonNameKey = "name"; const char* QGCSerialPortInfo::_jsonBoardClassKey = "boardClass";
const char* QGCSerialPortInfo::_jsonRegExpKey = "regExp"; const char* QGCSerialPortInfo::_jsonNameKey = "name";
const char* QGCSerialPortInfo::_jsonAndroidOnlyKey = "androidOnly"; const char* QGCSerialPortInfo::_jsonRegExpKey = "regExp";
const char* QGCSerialPortInfo::_jsonAndroidOnlyKey = "androidOnly";
const QGCSerialPortInfo::BoardClassString2BoardType_t QGCSerialPortInfo::_rgBoardClass2BoardType[] = { const QGCSerialPortInfo::BoardClassString2BoardType_t QGCSerialPortInfo::_rgBoardClass2BoardType[] = {
{ "Pixhawk", QGCSerialPortInfo::BoardTypePixhawk }, { "Pixhawk", QGCSerialPortInfo::BoardTypePixhawk },
@ -37,8 +38,9 @@ const QGCSerialPortInfo::BoardClassString2BoardType_t QGCSerialPortInfo::_rgBoar
{ "OpenPilot", QGCSerialPortInfo::BoardTypeOpenPilot }, { "OpenPilot", QGCSerialPortInfo::BoardTypeOpenPilot },
}; };
QList<QGCSerialPortInfo::BoardInfo_t> QGCSerialPortInfo::_boardInfoList; QList<QGCSerialPortInfo::BoardInfo_t> QGCSerialPortInfo::_boardInfoList;
QList<QGCSerialPortInfo::BoardFallback_t> QGCSerialPortInfo::_boardFallbackList; QList<QGCSerialPortInfo::BoardRegExpFallback_t> QGCSerialPortInfo::_boardDescriptionFallbackList;
QList<QGCSerialPortInfo::BoardRegExpFallback_t> QGCSerialPortInfo::_boardManufacturerFallbackList;
QGCSerialPortInfo::QGCSerialPortInfo(void) : QGCSerialPortInfo::QGCSerialPortInfo(void) :
QSerialPortInfo() QSerialPortInfo()
@ -90,8 +92,9 @@ void QGCSerialPortInfo::_loadJsonData(void)
// Validate root object keys // Validate root object keys
QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = { QList<JsonHelper::KeyValidateInfo> rootKeyInfoList = {
{ _jsonBoardInfoKey, QJsonValue::Array, true }, { _jsonBoardInfoKey, QJsonValue::Array, true },
{ _jsonBoardFallbackKey, QJsonValue::Array, true }, { _jsonBoardDescriptionFallbackKey, QJsonValue::Array, true },
{ _jsonBoardManufacturerFallbackKey, QJsonValue::Array, true },
}; };
if (!JsonHelper::validateKeys(json, rootKeyInfoList, errorString)) { if (!JsonHelper::validateKeys(json, rootKeyInfoList, errorString)) {
qWarning() << errorString; qWarning() << errorString;
@ -143,7 +146,7 @@ void QGCSerialPortInfo::_loadJsonData(void)
{ _jsonAndroidOnlyKey, QJsonValue::Bool, false }, { _jsonAndroidOnlyKey, QJsonValue::Bool, false },
}; };
QJsonArray rgBoardFallback = json[_jsonBoardFallbackKey].toArray(); QJsonArray rgBoardFallback = json[_jsonBoardDescriptionFallbackKey].toArray();
for (int i=0; i<rgBoardFallback.count(); i++) { for (int i=0; i<rgBoardFallback.count(); i++) {
const QJsonValue& jsonValue = rgBoardFallback[i]; const QJsonValue& jsonValue = rgBoardFallback[i];
if (!jsonValue.isObject()) { if (!jsonValue.isObject()) {
@ -157,17 +160,44 @@ void QGCSerialPortInfo::_loadJsonData(void)
return; return;
} }
BoardFallback_t boardFallback; BoardRegExpFallback_t boardFallback;
boardFallback.regExp = fallbackObject[_jsonRegExpKey].toString(); boardFallback.regExp = fallbackObject[_jsonRegExpKey].toString();
boardFallback.androidOnly = fallbackObject[_jsonAndroidOnlyKey].toBool(false); boardFallback.androidOnly = fallbackObject[_jsonAndroidOnlyKey].toBool(false);
boardFallback.boardType = _boardClassStringToType(fallbackObject[_jsonBoardClassKey].toString()); boardFallback.boardType = _boardClassStringToType(fallbackObject[_jsonBoardClassKey].toString());
if (boardFallback.boardType == BoardTypeUnknown) { if (boardFallback.boardType == BoardTypeUnknown) {
qWarning() << "Bad board class" << fallbackObject[_jsonBoardClassKey].toString(); qWarning() << "Bad board class" << fallbackObject[_jsonBoardClassKey].toString();
return; return;
} }
_boardFallbackList.append(boardFallback); _boardDescriptionFallbackList.append(boardFallback);
}
rgBoardFallback = json[_jsonBoardManufacturerFallbackKey].toArray();
for (int i=0; i<rgBoardFallback.count(); i++) {
const QJsonValue& jsonValue = rgBoardFallback[i];
if (!jsonValue.isObject()) {
qWarning() << "Entry in boardFallback array is not object";
return;
}
QJsonObject fallbackObject = jsonValue.toObject();
if (!JsonHelper::validateKeys(fallbackObject, fallbackKeyInfoList, errorString)) {
qWarning() << errorString;
return;
}
BoardRegExpFallback_t boardFallback;
boardFallback.regExp = fallbackObject[_jsonRegExpKey].toString();
boardFallback.androidOnly = fallbackObject[_jsonAndroidOnlyKey].toBool(false);
boardFallback.boardType = _boardClassStringToType(fallbackObject[_jsonBoardClassKey].toString());
if (boardFallback.boardType == BoardTypeUnknown) {
qWarning() << "Bad board class" << fallbackObject[_jsonBoardClassKey].toString();
return;
}
_boardManufacturerFallbackList.append(boardFallback);
} }
} }
@ -176,7 +206,6 @@ QGCSerialPortInfo::BoardType_t QGCSerialPortInfo::_boardClassStringToType(const
for (size_t j=0; j<sizeof(_rgBoardClass2BoardType)/sizeof(_rgBoardClass2BoardType[0]); j++) { for (size_t j=0; j<sizeof(_rgBoardClass2BoardType)/sizeof(_rgBoardClass2BoardType[0]); j++) {
if (boardClass == _rgBoardClass2BoardType[j].classString) { if (boardClass == _rgBoardClass2BoardType[j].classString) {
return _rgBoardClass2BoardType[j].boardType; return _rgBoardClass2BoardType[j].boardType;
break;
} }
} }
@ -196,7 +225,7 @@ bool QGCSerialPortInfo::getBoardInfo(QGCSerialPortInfo::BoardType_t& boardType,
for (int i=0; i<_boardInfoList.count(); i++) { for (int i=0; i<_boardInfoList.count(); i++) {
const BoardInfo_t& boardInfo = _boardInfoList[i]; const BoardInfo_t& boardInfo = _boardInfoList[i];
if (vendorIdentifier() == boardInfo.vendorId && productIdentifier() == boardInfo.productId) { if (vendorIdentifier() == boardInfo.vendorId && (productIdentifier() == boardInfo.productId || boardInfo.productId == 0)) {
boardType = boardInfo.boardType; boardType = boardInfo.boardType;
name = boardInfo.name; name = boardInfo.name;
return true; return true;
@ -204,10 +233,10 @@ bool QGCSerialPortInfo::getBoardInfo(QGCSerialPortInfo::BoardType_t& boardType,
} }
if (boardType == BoardTypeUnknown) { if (boardType == BoardTypeUnknown) {
// Fall back to port name matching which could lead to incorrect board mapping. But in some cases the // Fall back to port description matching and then manufactrure name matching
// vendor and product id do not come through correctly so this is used as a last chance detection method.
for (int i=0; i<_boardFallbackList.count(); i++) { for (int i=0; i<_boardDescriptionFallbackList.count(); i++) {
const BoardFallback_t& boardFallback = _boardFallbackList[i]; const BoardRegExpFallback_t& boardFallback = _boardDescriptionFallbackList[i];
if (description().contains(QRegExp(boardFallback.regExp, Qt::CaseInsensitive))) { if (description().contains(QRegExp(boardFallback.regExp, Qt::CaseInsensitive))) {
#ifndef __android #ifndef __android
@ -220,6 +249,21 @@ bool QGCSerialPortInfo::getBoardInfo(QGCSerialPortInfo::BoardType_t& boardType,
return true; return true;
} }
} }
for (int i=0; i<_boardManufacturerFallbackList.count(); i++) {
const BoardRegExpFallback_t& boardFallback = _boardManufacturerFallbackList[i];
if (manufacturer().contains(QRegExp(boardFallback.regExp, Qt::CaseInsensitive))) {
#ifndef __android
if (boardFallback.androidOnly) {
continue;
}
#endif
boardType = boardFallback.boardType;
name = _boardTypeToString(boardType);
return true;
}
}
} }
return false; return false;

8
src/comm/QGCSerialPortInfo.h

@ -68,7 +68,7 @@ private:
QString regExp; QString regExp;
BoardType_t boardType; BoardType_t boardType;
bool androidOnly; bool androidOnly;
} BoardFallback_t; } BoardRegExpFallback_t;
static void _loadJsonData(void); static void _loadJsonData(void);
static BoardType_t _boardClassStringToType(const QString& boardClass); static BoardType_t _boardClassStringToType(const QString& boardClass);
@ -77,7 +77,8 @@ private:
static bool _jsonLoaded; static bool _jsonLoaded;
static const char* _jsonFileTypeValue; static const char* _jsonFileTypeValue;
static const char* _jsonBoardInfoKey; static const char* _jsonBoardInfoKey;
static const char* _jsonBoardFallbackKey; static const char* _jsonBoardDescriptionFallbackKey;
static const char* _jsonBoardManufacturerFallbackKey;
static const char* _jsonVendorIDKey; static const char* _jsonVendorIDKey;
static const char* _jsonProductIDKey; static const char* _jsonProductIDKey;
static const char* _jsonBoardClassKey; static const char* _jsonBoardClassKey;
@ -87,6 +88,7 @@ private:
static const BoardClassString2BoardType_t _rgBoardClass2BoardType[BoardTypeUnknown]; static const BoardClassString2BoardType_t _rgBoardClass2BoardType[BoardTypeUnknown];
static QList<BoardInfo_t> _boardInfoList; static QList<BoardInfo_t> _boardInfoList;
static QList<BoardFallback_t> _boardFallbackList; static QList<BoardRegExpFallback_t> _boardDescriptionFallbackList;
static QList<BoardRegExpFallback_t> _boardManufacturerFallbackList;
}; };

19
src/comm/USBBoardInfo.json

@ -20,26 +20,29 @@
{ "vendorID": 9900, "productID": 22, "boardClass": "Pixhawk", "name": "Crazyflie 2" }, { "vendorID": 9900, "productID": 22, "boardClass": "Pixhawk", "name": "Crazyflie 2" },
{ "vendorID": 9900, "productID": 1, "boardClass": "Pixhawk", "name": "Omnibus F4 SD" }, { "vendorID": 9900, "productID": 1, "boardClass": "Pixhawk", "name": "Omnibus F4 SD" },
{ "vendorID": 8137, "productID": 28, "boardClass": "Pixhawk", "name": "PX4 NXPHlite v3.x" }, { "vendorID": 8137, "productID": 28, "boardClass": "Pixhawk", "name": "PX4 NXPHlite v3.x" },
{ "vendorID": 1155, "productID": 22336, "boardClass": "Pixhawk", "name": "ArduPilot ChibiOS" }, { "vendorID": 1155, "productID": 22336, "boardClass": "Pixhawk", "name": "ArduPilot ChibiOS" },
{ "vendorID": 4617, "productID": 22336, "boardClass": "Pixhawk", "name": "ArduPilot ChibiOS" }, { "vendorID": 4617, "productID": 22336, "boardClass": "Pixhawk", "name": "ArduPilot ChibiOS" },
{ "vendorID": 12642, "productID": 0, "boardClass": "Pixhawk", "name": "Holybro" },
{ "vendorID": 9900, "productID": 21, "boardClass": "PX4 Flow", "name": "PX4 Flow" }, { "vendorID": 9900, "productID": 21, "boardClass": "PX4 Flow", "name": "PX4 Flow" },
{ "vendorID": 1027, "productID": 24597, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "3DR Radio" }, { "vendorID": 1027, "productID": 24597, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "3DR Radio" },
{ "vendorID": 1027, "productID": 24577, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "3DR Radio on FTDI" }, { "vendorID": 1027, "productID": 24577, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "3DR Radio on FTDI" },
{ "vendorID": 4292, "productID": 60000, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "SILabs Radio" }, { "vendorID": 4292, "productID": 60000, "boardClass": "SiK Radio", "name": "SiK Radio", "comment": "SILabs Radio" },
{ "vendorID": 5446, "productID": 424, "boardClass": "RTK GPS", "name": "U-blox RTK GPS", "comment": "U-blox RTK GPS (M8P)" }, { "vendorID": 5446, "productID": 424, "boardClass": "RTK GPS", "name": "U-blox RTK GPS", "comment": "U-blox RTK GPS (M8P)" },
{ "vendorID": 5446, "productID": 425, "boardClass": "RTK GPS", "name": "U-blox RTK GPS", "comment": "U-blox RTK GPS (F9P)" }, { "vendorID": 5446, "productID": 425, "boardClass": "RTK GPS", "name": "U-blox RTK GPS", "comment": "U-blox RTK GPS (F9P)" },
{ "vendorID": 1317, "productID": 42151, "boardClass": "RTK GPS", "name": "Trimble RTK GPS", "comment": "Trimble RTK GPS" }, { "vendorID": 1317, "productID": 42151, "boardClass": "RTK GPS", "name": "Trimble RTK GPS" },
{ "vendorID": 5418, "productID": 34240, "boardClass": "RTK GPS", "name": "Septentrio RTK GPS", "comment": "Septentrio RTK GPS" }, { "vendorID": 5418, "productID": 34240, "boardClass": "RTK GPS", "name": "Septentrio RTK GPS" },
{ "vendorID": 8352, "productID": 16732, "boardClass": "OpenPilot", "name": "OpenPilot OPLink" }, { "vendorID": 8352, "productID": 16732, "boardClass": "OpenPilot", "name": "OpenPilot OPLink" },
{ "vendorID": 8352, "productID": 16733, "boardClass": "OpenPilot", "name": "OpenPilot CC3D" }, { "vendorID": 8352, "productID": 16733, "boardClass": "OpenPilot", "name": "OpenPilot CC3D" },
{ "vendorID": 8352, "productID": 16734, "boardClass": "OpenPilot", "name": "OpenPilot Revolution" }, { "vendorID": 8352, "productID": 16734, "boardClass": "OpenPilot", "name": "OpenPilot Revolution" },
{ "vendorID": 8352, "productID": 16848, "boardClass": "OpenPilot", "name": "Taulabs Sparky2" } { "vendorID": 8352, "productID": 16848, "boardClass": "OpenPilot", "name": "Taulabs Sparky2" }
], ],
"boardFallback": [ "boardDescriptionFallback": [
{ "regExp": "^PX4 FMU v5.x$", "boardClass": "Pixhawk" }, { "regExp": "^PX4 FMU v5.x$", "boardClass": "Pixhawk" },
{ "regExp": "^PX4 BL FMU v5.x$", "boardClass": "Pixhawk" }, { "regExp": "^PX4 BL FMU v5.x$", "boardClass": "Pixhawk" },
{ "regExp": "^PX4 FMU v4.x PRO$", "boardClass": "Pixhawk" }, { "regExp": "^PX4 FMU v4.x PRO$", "boardClass": "Pixhawk" },
@ -64,5 +67,11 @@
{ "regExp": "PX4.*Flow", "boardClass": "PX4 Flow" }, { "regExp": "PX4.*Flow", "boardClass": "PX4 Flow" },
{ "regExp": "^FT231X USB UART$", "boardClass": "SiK Radio" }, { "regExp": "^FT231X USB UART$", "boardClass": "SiK Radio" },
{ "regExp": "USB UART$", "boardClass": "SiK Radio", "androidOnly": true, "comment": "Very broad fallback, too dangerous for non-android" } { "regExp": "USB UART$", "boardClass": "SiK Radio", "androidOnly": true, "comment": "Very broad fallback, too dangerous for non-android" }
],
"boardManufacturerFallback": [
{ "regExp": "^ArduPilot$", "boardClass": "Pixhawk" },
{ "regExp": "^Hex/ProfiCNC$", "boardClass": "Pixhawk" },
{ "regExp": "^Holybro$", "boardClass": "Pixhawk" }
] ]
} }

Loading…
Cancel
Save