mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-07-24 15:27:41 +08:00
chore(uavcan): remove FW flashing database (#27930)
* feat(uavcan): remove FW.db generation * docs(dronecan): remove FW.db section, update remote update workflow
This commit is contained in:
@@ -328,31 +328,12 @@ On boot, PX4 scans both locations, reads the board ID from the _APDescriptor_ of
|
||||
The source file is then deleted.
|
||||
Any connected node whose running version does not match is then flashed over the CAN bus.
|
||||
|
||||
### Firmware Database
|
||||
|
||||
A flat-file database at `/fs/microsd/ufw/FW.db` maps each board ID to the original firmware filename that was installed.
|
||||
This may be queried by external tools to determine current firmware versions.
|
||||
|
||||
Example entry:
|
||||
|
||||
```txt
|
||||
122.bin=122-1.17.63eeff1a.uavcan.bin
|
||||
```
|
||||
|
||||
Entries are removed on boot if their corresponding firmware is not present.
|
||||
|
||||
### Remote Update
|
||||
|
||||
Remote updates can be made by uploading the corresponding bin files to `/fs/microsd/ufw_staging/`.
|
||||
PX4 will then update firmware on next boot.
|
||||
|
||||
This approach enables efficient mass-update of binaries from archives (`.zip` or `.tar` that contains `.bin` files for the target CAN nodes).
|
||||
Tools can:
|
||||
|
||||
1. Read the PX4 firmware database to determine what firmware is present
|
||||
2. Extract the more-recent versions of matching firmware to the staging directory
|
||||
|
||||
PX4 does not provide such tools.
|
||||
|
||||
::: info
|
||||
Auterion uses a form of this workflow to update CAN firmware to SkyNode based devices.
|
||||
@@ -366,7 +347,7 @@ The `upload_skynode.sh` script with multiple `--ext-fw` flags is used to bundle
|
||||
--ext-fw=build/auterion_canio_default/some_other_default.uavcan.bin
|
||||
```
|
||||
|
||||
Another tool then checks the firmware database and extracts just the relevant files to the PX4 firmware staging area.
|
||||
Another tool then checks which files were already uploaded using a local database and extracts just the relevant files to the PX4 firmware staging area.
|
||||
:::
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -56,9 +56,6 @@
|
||||
#include <uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp>
|
||||
#include <uavcan_posix/firmware_version_checker.hpp>
|
||||
|
||||
static constexpr size_t FW_DB_LINE_SIZE = 256; // key(~15) + '=' + filename(NAME_MAX) + '\n'
|
||||
static const char FW_DB_PATH[] = UAVCAN_FIRMWARE_PATH "/FW.db";
|
||||
static const char FW_DB_TMP_PATH[] = UAVCAN_FIRMWARE_PATH "/FW.db.tmp";
|
||||
static uint8_t _buffer[512]
|
||||
px4_cache_aligned_data() = {};
|
||||
|
||||
@@ -142,9 +139,6 @@ int UavcanServers::init()
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if all entries in the firmware database are still valid */
|
||||
validateFwDatabase();
|
||||
|
||||
/*
|
||||
Check for firmware in the root directory, move it to appropriate location on
|
||||
the SD card, as defined by the APDesc.
|
||||
@@ -236,7 +230,6 @@ void UavcanServers::migrateFWFromRoot(const char *sd_path, const char *sd_root_p
|
||||
snprintf(dstpath, sizeof(dstpath), "%s/%d.bin", sd_path, descriptor.board_id);
|
||||
|
||||
if (copyFw(dstpath, srcpath) >= 0) {
|
||||
updateFwDatabase(dstpath, bin_names[i]);
|
||||
unlink(srcpath);
|
||||
}
|
||||
}
|
||||
@@ -296,112 +289,3 @@ int UavcanServers::copyFw(const char *dst, const char *src)
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void UavcanServers::updateFwDatabase(const char *fw_path, const char *original_filename)
|
||||
{
|
||||
// DB key is the filename portion of fw_path, e.g. "12345.bin"
|
||||
const char *last_slash = strrchr(fw_path, '/');
|
||||
const char *new_filename = last_slash ? (last_slash + 1) : fw_path;
|
||||
|
||||
// The new/updated DB entry, e.g. "122.bin=122-1.17.63eeff1a.uavcan-dev.bin\n"
|
||||
char new_entry[FW_DB_LINE_SIZE];
|
||||
snprintf(new_entry, sizeof(new_entry), "%s=%s\n", new_filename, original_filename);
|
||||
|
||||
// Open the existing DB for reading (may not exist yet) and a temp file for writing.
|
||||
FILE *db_in = fopen(FW_DB_PATH, "r");
|
||||
FILE *db_out = fopen(FW_DB_TMP_PATH, "w");
|
||||
|
||||
if (!db_out) {
|
||||
if (db_in) { fclose(db_in); }
|
||||
|
||||
PX4_WARN("updateFwDatabase: couldn't open tmp file");
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy all existing entries to the temp file, replacing the matching key in-place.
|
||||
bool line_updated = false;
|
||||
char line[FW_DB_LINE_SIZE];
|
||||
|
||||
if (db_in) {
|
||||
while (fgets(line, sizeof(line), db_in)) {
|
||||
if (strncmp(line, new_filename, strlen(new_filename)) == 0 && line[strlen(new_filename)] == '=') {
|
||||
fputs(new_entry, db_out);
|
||||
line_updated = true;
|
||||
|
||||
} else {
|
||||
fputs(line, db_out);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(db_in);
|
||||
}
|
||||
|
||||
// Key was not present in the existing DB — append it as a new entry.
|
||||
if (!line_updated) {
|
||||
fputs(new_entry, db_out);
|
||||
}
|
||||
|
||||
fflush(db_out);
|
||||
fsync(fileno(db_out));
|
||||
fclose(db_out);
|
||||
|
||||
// Atomically replace the old DB with the updated version.
|
||||
rename(FW_DB_TMP_PATH, FW_DB_PATH);
|
||||
}
|
||||
|
||||
void UavcanServers::validateFwDatabase()
|
||||
{
|
||||
FILE *db_in = fopen(FW_DB_PATH, "r");
|
||||
|
||||
if (!db_in) {
|
||||
return; // no DB yet, nothing to validate
|
||||
}
|
||||
|
||||
FILE *db_out = fopen(FW_DB_TMP_PATH, "w");
|
||||
|
||||
if (!db_out) {
|
||||
fclose(db_in);
|
||||
PX4_WARN("validateFwDatabase: couldn't open tmp file");
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
char line[FW_DB_LINE_SIZE];
|
||||
|
||||
while (fgets(line, sizeof(line), db_in)) {
|
||||
// Each valid line is "key=original_filename\n", e.g. "122.bin=122-1.17.abc.bin"
|
||||
const char *eq = strchr(line, '=');
|
||||
|
||||
if (eq == nullptr) {
|
||||
changed = true; // malformed line — drop it
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build the full path to the firmware file to check if it still exists.
|
||||
char full_path[UAVCAN_MAX_PATH_LENGTH + 1];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%.*s", UAVCAN_FIRMWARE_PATH,
|
||||
(int)(eq - line), line);
|
||||
|
||||
struct stat sb;
|
||||
|
||||
if (stat(full_path, &sb) == 0 && S_ISREG(sb.st_mode)) {
|
||||
fputs(line, db_out);
|
||||
|
||||
} else {
|
||||
PX4_INFO("validateFwDatabase: removing stale entry for '%.*s'", (int)(eq - line), line);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(db_in);
|
||||
fflush(db_out);
|
||||
fsync(fileno(db_out));
|
||||
fclose(db_out);
|
||||
|
||||
if (changed) {
|
||||
rename(FW_DB_TMP_PATH, FW_DB_PATH);
|
||||
|
||||
} else {
|
||||
unlink(FW_DB_TMP_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,6 @@ private:
|
||||
void unpackFwFromROMFS(const char *sd_path, const char *romfs_path);
|
||||
void migrateFWFromRoot(const char *sd_path, const char *sd_root_path);
|
||||
int copyFw(const char *dst, const char *src);
|
||||
void updateFwDatabase(const char *fw_path, const char *original_filename);
|
||||
void validateFwDatabase();
|
||||
|
||||
uavcan_posix::dynamic_node_id_server::FileEventTracer _tracer;
|
||||
uavcan_posix::dynamic_node_id_server::FileStorageBackend _storage_backend;
|
||||
|
||||
Reference in New Issue
Block a user