为什么QGC能安全升级飞控固件?深入QGroundControl固件升级系统源码,解析Bootloader通信与固件校验机制
一、固件升级系统概述
1.1 为什么需要固件升级系统
无人机飞控固件需要定期升级以修复bug、增加新功能。QGC的固件升级系统解决三个核心问题:
- 安全传输:通过Bootloader可靠地烧录固件到飞控Flash
- 固件校验:确保固件完整性与合法性(CRC、签名)
- 失败恢复:支持固件升级失败后的恢复模式
1.2 核心类架构
QGroundControl/
├── src/
│ ├── FirmwareUpgrade/
│ │ ├── FirmwareUpgradeManager.h/cpp # 固件升级管理器
│ │ ├── BootloaderManager.h/cpp # Bootloader通信管理
│ │ ├── FirmwareImage.h/cpp # 固件镜像解析
│ │ └── FirmwareHashMatch.h/cpp # 固件哈希校验
│ ├── QSerialPortIntegration/
│ │ └── SerialLink.h/cpp # 串口通信链路
│ └── QmlControls/FirmwareUpgrade/
│ └── QmlFirmwareUpgrade.h/cpp # QML升级界面接口
1.3 支持的飞控类型
| 飞控类型 | Bootloader协议 | 固件格式 |
|---|---|---|
| PX4 | PX4 Bootloader | .px4 (JSON + 二进制) |
| ArduPilot | ArduPilot Bootloader | .apj (JSON) |
| STM32 | DFU模式 | .bin/.hex |
二、FirmwareUpgradeManager核心实现
2.1 升级管理器状态机
cpp
// src/FirmwareUpgrade/FirmwareUpgradeManager.h
class FirmwareUpgradeManager : public QObject
{
Q_OBJECT
public:
explicit FirmwareUpgradeManager(QObject* parent = nullptr);
~FirmwareUpgradeManager();
// 升级接口
Q_INVOKABLE bool startUpgrade(const QString& firmwarePath);
Q_INVOKABLE void cancelUpgrade();
// 固件信息查询
Q_INVOKABLE QString firmwareVersion() const;
Q_INVOKABLE QString boardType() const;
// 升级进度
Q_PROPERTY(float upgradeProgress READ upgradeProgress NOTIFY upgradeProgressChanged)
float upgradeProgress() const { return m_upgradeProgress; }
signals:
void upgradeProgressChanged(float progress);
void upgradeComplete(bool success, const QString& errorString = QString());
void boardFound(const QString& boardName);
private slots:
void _bootloaderConnected();
void _firmwareWritten(uint32_t bytesWritten);
void _verificationComplete(bool success);
private:
// 状态机
enum UpgradeState {
UpgradeStateIdle,
UpgradeStateConnecting,
UpgradeStateErasing,
UpgradeStateFlashing,
UpgradeStateVerifying,
UpgradeStateComplete
};
// 状态转换
void _setUpgradeState(UpgradeState state);
void _advanceState();
// 各阶段实现
bool _connectToBootloader();
bool _eraseFlash();
bool _flashFirmware();
bool _verifyFirmware();
// 工具方法
bool _rebootToBootloader();
bool _waitForBootloader(int timeoutMs);
BootloaderManager* m_bootloaderManager;
FirmwareImage* m_firmwareImage;
UpgradeState m_upgradeState;
float m_upgradeProgress;
// 统计信息
uint32_t m_totalBytes;
uint32_t m_bytesWritten;
};
2.2 固件镜像解析(源码级)
cpp
// src/FirmwareUpgrade/FirmwareImage.cpp
bool FirmwareImage::loadFromFile(const QString& filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
m_errorString = tr("Failed to open firmware file: ") + file.errorString();
return false;
}
QByteArray fileData = file.readAll();
file.close();
// 尝试解析为PX4 .px4格式(JSON + 二进制)
if (filePath.endsWith(".px4")) {
return _parsePX4Firmware(fileData);
}
// 尝试解析为ArduPilot .apj格式(JSON)
if (filePath.endsWith(".apj")) {
return _parseArduPilotFirmware(fileData);
}
// 原始二进制格式
if (filePath.endsWith(".bin")) {
return _parseBinaryFirmware(fileData);
}
m_errorString = tr("Unsupported firmware format");
return false;
}
bool FirmwareImage::_parsePX4Firmware(const QByteArray& data)
{
// PX4固件格式:JSON头部 + 二进制固件
// JSON以'\0'结束,后跟二进制数据
// 查找JSON结束位置
int jsonEnd = data.indexOf('\0');
if (jsonEnd == -1) {
m_errorString = tr("Invalid PX4 firmware: no JSON terminator");
return false;
}
// 解析JSON元数据
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data.left(jsonEnd), &parseError);
if (parseError.error != QJsonParseError::NoError) {
m_errorString = tr("Failed to parse firmware JSON: ") + parseError.errorString();
return false;
}
QJsonObject rootObj = jsonDoc.object();
// 提取元数据
m_boardType = rootObj["board_type"].toString();
m_firmwareVersion = rootObj["version"].toString();
m_imageSize = rootObj["image_size"].toInt();
// 提取二进制固件数据(JSON之后)
m_firmwareData = data.mid(jsonEnd + 1);
if (m_firmwareData.size() != m_imageSize) {
m_errorString = tr("Firmware size mismatch: expected %1, got %2")
.arg(m_imageSize).arg(m_firmwareData.size());
return false;
}
// 计算CRC32校验
m_crc32 = _calculateCRC32(m_firmwareData);
qDebug() << "Loaded PX4 firmware:" << m_firmwareVersion
<< "for board:" << m_boardType
<< "size:" << m_firmwareData.size() << "bytes";
return true;
}
uint32_t FirmwareImage::_calculateCRC32(const QByteArray& data)
{
// 使用zlib的CRC32函数
return crc32(0, reinterpret_cast<const Bytef*>(data.constData()), data.size());
}
三、BootloaderManager核心实现
3.1 Bootloader通信协议
PX4 Bootloader使用简单的二进制协议通过串口通信:
命令格式:
┌─────────┬─────────┬──────────┬─────────┬─────────┐
│ 同步头 │ 命令ID │ 数据长度 │ 数据 │ CRC16 │
│ 2字节 │ 1字节 │ 2字节 │ N字节 │ 2字节 │
└─────────┴─────────┴──────────┴─────────┴─────────┘
cpp
// src/FirmwareUpgrade/BootloaderManager.h
class BootloaderManager : public QObject
{
Q_OBJECT
public:
explicit BootloaderManager(QObject* parent = nullptr);
~BootloaderManager();
// 连接/断开Bootloader
bool connectToBootloader(const QString& portName, int baudRate = 115200);
void disconnectBootloader();
// Bootloader命令
bool getBoardInfo(QString& boardName, uint32_t& boardID);
bool eraseFlash(uint32_t startAddr, uint32_t size);
bool writeFlash(uint32_t addr, const QByteArray& data);
bool readFlash(uint32_t addr, uint32_t size, QByteArray& data);
bool verifyFlash(uint32_t addr, const QByteArray& expectedData);
bool reboot();
signals:
void boardConnected(const QString& boardName);
void boardDisconnected();
void writeProgress(uint32_t bytesWritten, uint32_t totalBytes);
private:
// 协议实现
bool _sendCommand(uint8_t cmdID, const QByteArray& data = QByteArray());
bool _waitForResponse(uint8_t expectedCmdID, QByteArray& response, int timeoutMs = 5000);
uint16_t _calculateCRC16(const QByteArray& data);
// 帧格式
struct BootloaderFrame {
uint16_t sync; // 0xDEAD
uint8_t cmdID;
uint16_t dataLen;
QByteArray data;
uint16_t crc16;
};
// 命令ID
enum BootloaderCmd {
CmdGetBoardInfo = 0x01,
CmdEraseFlash = 0x02,
CmdWriteFlash = 0x03,
CmdReadFlash = 0x04,
CmdVerifyFlash = 0x05,
CmdReboot = 0x06
};
QSerialPort* m_serialPort;
bool m_connected;
};
3.2 Bootloader连接实现(源码级)
cpp
// src/FirmwareUpgrade/BootloaderManager.cpp
bool BootloaderManager::connectToBootloader(const QString& portName, int baudRate)
{
m_serialPort = new QSerialPort(this);
m_serialPort->setPortName(portName);
m_serialPort->setBaudRate(baudRate);
m_serialPort->setDataBits(QSerialPort::Data8);
m_serialPort->setParity(QSerialPort::NoParity);
m_serialPort->setStopBits(QSerialPort::OneStop);
m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
if (!m_serialPort->open(QIODevice::ReadWrite)) {
qWarning() << "Failed to open serial port:" << portName
<< m_serialPort->errorString();
return false;
}
// 发送同步命令,等待Bootloader响应
QByteArray syncCmd;
QDataStream ds(&syncCmd, QIODevice::WriteOnly);
ds.setByteOrder(QDataStream::LittleEndian);
ds << static_cast<uint16_t>(0xDEAD) // 同步头
<< static_cast<uint8_t>(CmdGetBoardInfo)
<< static_cast<uint16_t>(0); // 无数据
// 添加CRC16
uint16_t crc = _calculateCRC16(syncCmd);
ds << crc;
m_serialPort->write(syncCmd);
m_serialPort->waitForBytesWritten(1000);
// 等待响应
QByteArray response;
if (!_waitForResponse(CmdGetBoardInfo, response, 3000)) {
qWarning() << "No response from bootloader";
m_serialPort->close();
return false;
}
// 解析响应
QString boardName;
uint32_t boardID;
QDataStream rxDs(response);
rxDs.setByteOrder(QDataStream::LittleEndian);
rxDs >> boardID;
char boardNameBuf[32];
rxDs.readRawData(boardNameBuf, sizeof(boardNameBuf));
boardName = QString::fromLatin1(boardNameBuf);
m_connected = true;
emit boardConnected(boardName);
qDebug() << "Connected to bootloader:" << boardName
<< "board ID:" << boardID;
return true;
}
3.3 固件写入实现
cpp
bool BootloaderManager::writeFlash(uint32_t addr, const QByteArray& data)
{
if (!m_connected || !m_serialPort) {
return false;
}
// Bootloader通常限制每次写入的最大字节数(如256字节)
const uint32_t maxChunkSize = 256;
uint32_t offset = 0;
while (offset < static_cast<uint32_t>(data.size())) {
uint32_t chunkSize = qMin(maxChunkSize, static_cast<uint32_t>(data.size()) - offset);
// 构建写入命令
QByteArray cmdData;
QDataStream ds(&cmdData, QIODevice::WriteOnly);
ds.setByteOrder(QDataStream::LittleEndian);
ds << addr + offset
<< chunkSize;
// 添加固件数据
cmdData.append(data.mid(offset, chunkSize));
// 发送命令
if (!_sendCommand(CmdWriteFlash, cmdData)) {
qWarning() << "Failed to send write command at offset" << offset;
return false;
}
// 等待确认
QByteArray response;
if (!_waitForResponse(CmdWriteFlash, response, 5000)) {
qWarning() << "No acknowledge from bootloader at offset" << offset;
return false;
}
offset += chunkSize;
// 进度回调
emit writeProgress(offset, data.size());
}
return true;
}
四、固件升级完整流程
4.1 升级状态机实现
cpp
// src/FirmwareUpgrade/FirmwareUpgradeManager.cpp
void FirmwareUpgradeManager::_setUpgradeState(UpgradeState state)
{
if (m_upgradeState == state) return;
m_upgradeState = state;
QString stateStr;
switch (state) {
case UpgradeStateIdle: stateStr = "Idle"; break;
case UpgradeStateConnecting: stateStr = "Connecting"; break;
case UpgradeStateErasing: stateStr = "Erasing Flash"; break;
case UpgradeStateFlashing: stateStr = "Flashing Firmware"; break;
case UpgradeStateVerifying: stateStr = "Verifying Firmware"; break;
case UpgradeStateComplete: stateStr = "Complete"; break;
}
qDebug() << "Upgrade state changed to:" << stateStr;
}
bool FirmwareUpgradeManager::startUpgrade(const QString& firmwarePath)
{
if (m_upgradeState != UpgradeStateIdle) {
m_errorString = tr("Upgrade already in progress");
return false;
}
// 加载固件镜像
m_firmwareImage = new FirmwareImage(this);
if (!m_firmwareImage->loadFromFile(firmwarePath)) {
m_errorString = m_firmwareImage->errorString();
return false;
}
// 开始升级流程
_setUpgradeState(UpgradeStateConnecting);
// 连接Bootloader
if (!_connectToBootloader()) {
_setUpgradeState(UpgradeStateIdle);
return false;
}
return true;
}
bool FirmwareUpgradeManager::_connectToBootloader()
{
// 首先尝试重新启动飞控到Bootloader模式
if (!_rebootToBootloader()) {
qWarning() << "Failed to reboot to bootloader, trying manual connection";
}
// 等待Bootloader连接
QTimer::singleShot(1000, this, [this]() {
if (m_bootloaderManager->connectToBootloader(m_portName)) {
_bootloaderConnected();
} else {
emit upgradeComplete(false, tr("Failed to connect to bootloader"));
_setUpgradeState(UpgradeStateIdle);
}
});
return true;
}
void FirmwareUpgradeManager::_bootloaderConnected()
{
_setUpgradeState(UpgradeStateErasing);
_advanceState();
}
void FirmwareUpgradeManager::_advanceState()
{
switch (m_upgradeState) {
case UpgradeStateErasing:
if (!_eraseFlash()) {
emit upgradeComplete(false, tr("Failed to erase flash"));
_setUpgradeState(UpgradeStateIdle);
return;
}
_setUpgradeState(UpgradeStateFlashing);
// 继续执行...
case UpgradeStateFlashing:
if (!_flashFirmware()) {
emit upgradeComplete(false, tr("Failed to flash firmware"));
_setUpgradeState(UpgradeStateIdle);
return;
}
_setUpgradeState(UpgradeStateVerifying);
// 继续执行...
case UpgradeStateVerifying:
if (!_verifyFirmware()) {
emit upgradeComplete(false, tr("Firmware verification failed"));
_setUpgradeState(UpgradeStateIdle);
return;
}
_setUpgradeState(UpgradeStateComplete);
emit upgradeComplete(true);
break;
}
}
4.2 固件擦除实现
cpp
bool FirmwareUpgradeManager::_eraseFlash()
{
if (!m_bootloaderManager || !m_firmwareImage) {
return false;
}
qDebug() << "Erasing flash...";
// 擦除固件区域(通常从地址0x08000000开始)
uint32_t startAddr = 0x08000000; // STM32 Flash起始地址
uint32_t size = m_firmwareImage->imageSize();
if (!m_bootloaderManager->eraseFlash(startAddr, size)) {
qWarning() << "Failed to erase flash";
return false;
}
qDebug() << "Flash erased:" << size << "bytes";
return true;
}
4.3 固件写入与校验
cpp
bool FirmwareUpgradeManager::_flashFirmware()
{
if (!m_bootloaderManager || !m_firmwareImage) {
return false;
}
qDebug() << "Flashing firmware...";
QByteArray firmwareData = m_firmwareImage->firmwareData();
uint32_t startAddr = 0x08000000;
// 连接写入进度信号
connect(m_bootloaderManager, &BootloaderManager::writeProgress,
this, &FirmwareUpgradeManager::_onWriteProgress);
if (!m_bootloaderManager->writeFlash(startAddr, firmwareData)) {
qWarning() << "Failed to write firmware";
return false;
}
qDebug() << "Firmware flashed successfully";
return true;
}
void FirmwareUpgradeManager::_onWriteProgress(uint32_t bytesWritten, uint32_t totalBytes)
{
// 更新进度(写入占80%,校验占20%)
float progress = static_cast<float>(bytesWritten) / totalBytes * 0.8f;
m_upgradeProgress = progress;
emit upgradeProgressChanged(progress);
}
bool FirmwareUpgradeManager::_verifyFirmware()
{
if (!m_bootloaderManager || !m_firmwareImage) {
return false;
}
qDebug() << "Verifying firmware...";
QByteArray firmwareData = m_firmwareImage->firmwareData();
uint32_t startAddr = 0x08000000;
// 读取Flash内容并比较
QByteArray flashData;
if (!m_bootloaderManager->readFlash(startAddr, firmwareData.size(), flashData)) {
qWarning() << "Failed to read flash for verification";
return false;
}
// CRC校验
uint32_t expectedCRC = m_firmwareImage->crc32();
uint32_t actualCRC = _calculateCRC32(flashData);
if (expectedCRC != actualCRC) {
qWarning() << "CRC mismatch: expected" << expectedCRC << "got" << actualCRC;
return false;
}
// 字节比对(可选,耗时)
if (flashData != firmwareData) {
qWarning() << "Firmware data mismatch";
return false;
}
m_upgradeProgress = 1.0f;
emit upgradeProgressChanged(1.0f);
qDebug() << "Firmware verification passed";
// 重启飞控
m_bootloaderManager->reboot();
return true;
}
五、QML升级界面
5.1 固件升级面板
qml
// src/QmlControls/FirmwareUpgrade/FirmwareUpgradePanel.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QGroundControl.FirmwareUpgrade 1.0
Item {
id: root
property var upgradeManager: QGroundControl.firmwareUpgradeManager
width: 500
height: 400
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// 标题
Label {
text: "Firmware Upgrade"
font.pointSize: 16
font.bold: true
}
// 固件文件选择
RowLayout {
Label {
text: "Firmware File:"
}
TextField {
id: firmwarePathField
Layout.fillWidth: true
placeholderText: "Select firmware file..."
readOnly: true
}
Button {
text: "Browse"
onClicked: {
var fileUrl = QGroundControl.fileDialog("Select Firmware File",
"Firmware Files (*.px4 *.apj *.bin)");
if (fileUrl) {
firmwarePathField.text = fileUrl;
}
}
}
}
// 固件信息显示
ColumnLayout {
visible: firmwarePathField.text !== ""
Label {
text: "Board: " + upgradeManager.boardType
}
Label {
text: "Version: " + upgradeManager.firmwareVersion
}
Label {
text: "Size: " + (upgradeManager.firmwareSize / 1024).toFixed(1) + " KB"
}
}
// 升级进度条
ProgressBar {
id: upgradeProgressBar
Layout.fillWidth: true
from: 0.0
to: 1.0
value: upgradeManager.upgradeProgress
visible: upgradeManager.upgradeInProgress
}
// 升级按钮
RowLayout {
Button {
text: upgradeManager.upgradeInProgress ? "Cancel" : "Start Upgrade"
enabled: firmwarePathField.text !== "" || upgradeManager.upgradeInProgress
onClicked: {
if (upgradeManager.upgradeInProgress) {
upgradeManager.cancelUpgrade()
} else {
upgradeManager.startUpgrade(firmwarePathField.text)
}
}
}
}
// 状态信息
Label {
id: statusLabel
text: upgradeManager.statusMessage
color: upgradeManager.upgradeSucceeded ? "green" :
upgradeManager.upgradeFailed ? "red" : "black"
}
}
}
六、DFU模式支持
6.1 DFU升级流程
对于支持USB DFU(Device Firmware Upgrade)的飞控,可以通过USB直接升级:
cpp
// src/FirmwareUpgrade/DFUManager.h
class DFUManager : public QObject
{
Q_OBJECT
public:
explicit DFUManager(QObject* parent = nullptr);
// DFU操作
bool enterDFUMode();
bool exitDFUMode();
bool downloadFirmware(const QByteArray& firmwareData);
bool uploadFirmware(QByteArray& firmwareData);
bool leaveDFUMode();
private:
// USB设备查找
bool _findDFUDevice();
// DFU状态机
enum DFUState {
DFUStateIdle,
DFUStateDownload,
DFUStateManifest,
DFUStateDetach
};
// USB通信
libusb_device_handle* m_usbHandle;
DFUState m_dfuState;
};
6.2 DFU下载实现(源码级)
cpp
// src/FirmwareUpgrade/DFUManager.cpp
bool DFUManager::downloadFirmware(const QByteArray& firmwareData)
{
if (!m_usbHandle) {
qWarning() << "No DFU device connected";
return false;
}
// DFU下载协议:将固件分块传输到设备
const uint32_t blockSize = 1024; // DFU标准块大小
uint32_t totalBlocks = (firmwareData.size() + blockSize - 1) / blockSize;
for (uint32_t blockNum = 0; blockNum < totalBlocks; ++blockNum) {
uint32_t offset = blockNum * blockSize;
uint32_t thisBlockSize = qMin(blockSize, static_cast<uint32_t>(firmwareData.size()) - offset);
// 构建DFU下载请求
int ret = libusb_control_transfer(
m_usbHandle,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
0x01, // DFU_DNLOAD
blockNum,
0, // Interface
reinterpret_cast<unsigned char*>(firmwareData.data() + offset),
thisBlockSize,
5000 // 5秒超时
);
if (ret < 0) {
qWarning() << "DFU download failed at block" << blockNum << libusb_error_name(ret);
return false;
}
// 获取状态
ret = libusb_control_transfer(
m_usbHandle,
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
0x03, // DFU_GETSTATUS
0,
0,
m_statusBuffer,
sizeof(m_statusBuffer),
5000
);
if (ret < 0) {
qWarning() << "DFU get status failed:" << libusb_error_name(ret);
return false;
}
// 检查状态
uint8_t status = m_statusBuffer[0];
if (status != 0x00) { // OK
qWarning() << "DFU status error:" << status;
return false;
}
// 更新进度
float progress = static_cast<float>(blockNum + 1) / totalBlocks;
emit downloadProgress(progress);
}
// 发送下载完成(零长度包)
libusb_control_transfer(
m_usbHandle,
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
0x01, // DFU_DNLOAD
totalBlocks,
0,
nullptr,
0,
5000
);
qDebug() << "DFU download complete";
return true;
}
七、失败恢复与安全机制
7.1 失败恢复策略
cpp
// 固件升级失败后的恢复机制
void FirmwareUpgradeManager::_handleUpgradeFailure(const QString& errorString)
{
qWarning() << "Firmware upgrade failed:" << errorString;
// 尝试重新连接到Bootloader
if (m_retryCount < m_maxRetries) {
m_retryCount++;
qDebug() << "Retrying upgrade (attempt" << m_retryCount << "of" << m_maxRetries << ")";
QTimer::singleShot(2000, this, [this]() {
_connectToBootloader();
});
return;
}
// 超过重试次数,进入恢复模式
_enterRecoveryMode();
}
void FirmwareUpgradeManager::_enterRecoveryMode()
{
qWarning() << "Entering firmware recovery mode";
// 提示用户手动进入Bootloader模式
emit showRecoveryInstructions(
tr("Firmware upgrade failed. Please:\n")
tr("1. Disconnect the battery\n")
tr("2. Hold the boot button\n")
tr("3. Connect USB\n")
tr("4. Release the boot button\n")
tr("5. Retry firmware upgrade")
);
// 设置状态为Idle,允许用户重试
_setUpgradeState(UpgradeStateIdle);
}
7.2 固件签名校验
cpp
// 固件签名校验(防止恶意固件)
bool FirmwareImage::_verifySignature(const QByteArray& firmwareData,
const QByteArray& signature,
const QByteArray& publicKey)
{
// 使用OpenSSL验证RSA签名
EVP_PKEY* pkey = _loadPublicKey(publicKey);
if (!pkey) {
qWarning() << "Failed to load public key";
return false;
}
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
EVP_VerifyInit_ex(mdctx, EVP_sha256(), nullptr);
EVP_VerifyUpdate(mdctx, firmwareData.constData(), firmwareData.size());
int ret = EVP_VerifyFinal(mdctx,
reinterpret_cast<const unsigned char*>(signature.constData()),
signature.size(),
pkey);
EVP_MD_CTX_free(mdctx);
EVP_PKEY_free(pkey);
if (ret == 1) {
qDebug() << "Firmware signature verified successfully";
return true;
} else {
qWarning() << "Firmware signature verification failed";
return false;
}
}
八、总结
QGC固件升级系统核心要点:
- 升级管理器:FirmwareUpgradeManager状态机,管理升级全流程
- Bootloader通信:BootloaderManager实现串口Bootloader协议
- 固件解析:FirmwareImage解析.px4/.apj/.bin格式
- 固件写入:分块写入Flash,支持进度回调
- 校验机制:CRC32校验、签名验证
- DFU支持:通过USB DFU模式升级
- 失败恢复:重试机制、恢复模式
固件升级是无人机地面站的关键功能,理解其架构对开发可靠的升级系统至关重要。
《注:若有发现问题欢迎大家提出来纠正》