#esp32 #update #esp #flash #ota #api-bindings

esp-ota

仅使用安全的Rust为ESP32芯片提供简单的OTA更新。不依赖传输方式。

2个不稳定版本

0.2.0 2023年7月9日
0.1.0 2022年10月1日
0.0.1 2022年9月30日

#1040嵌入式开发

MIT/Apache

18KB
200

esp-ota

此crate允许使用仅安全的Rust为ESP32芯片提供简单的OTA更新。该crate完全不依赖于传输方式,这意味着它不处理如何将新的应用程序映像传输到ESP。

esp-idf-svc 的比较

在编写此库后,我了解到 esp-idf-svc crate 有实验性的OTA更新支持。它“隐藏”在一个在生成的文档中不可见的模块中,因为这个功能默认未启用,并且在生成文档时也未被启用。

用法

本节将解释如何在应用程序中使用 esp-ota 将下载的应用程序映像写入闪存并从中启动。

分区表

芯片必须至少有两个 app, ota_X 分区,以便可以从一个分区启动,并将OTA更新写入另一个分区。还有一个 data, ota 分区来存储有关引导加载程序应从哪个分区启动的信息。

创建一个名为 partitions.csv 的文件。您可以在espressifs网站上了解更多关于 ESP分区表 的信息。但这里有一个适用于4M闪存的相当默认的示例

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x4000,
otadata,  data, ota,     0xd000,  0x2000,
phy_init, data, phy,     0xf000,  0x1000,
ota_0,    app,  ota_0,   0x10000, 0x180000,
ota_1,    app,  ota_1,   0x190000, 0x180000,

并在 Cargo.toml 中告诉 espflash 使用它。更多信息请参阅 cargo espflash 文档

[package.metadata.espflash]
partition_table = "partitions.csv"

应用程序映像格式

您要烧录的应用程序必须具有正确的格式。它不应该是在ESP项目中通过常规 cargo build 产生的ELF可执行文件,而应该是ESP32特定的 应用程序映像格式

可以使用 esptool.py elf2imageespflash save-image 将二进制文件转换为应用程序映像

$ esptool.py --chip ESP32-C3 elf2image --output my-app.bin target/release/my-app
$ espflash save-image ESP32-C3 target/release/my-app my-app.bin

代码

要将新应用程序闪存到下一个分区,请包含类似以下代码:

// This is a very unrealistic example. You usually don't store the new app in the
// old app. Instead you obtain it by downloading it from somewhere or similar.
const NEW_APP: &[u8] = include_bytes!("../my-app.bin");

// Finds the next suitable OTA partition and erases it
let mut ota = esp_ota::OtaUpdate::begin()?;

// Write the app to flash. Normally you would download
// the app and call `ota.write` every time you have obtained
// a part of the app image. This example is not realistic,
// since it has the entire new app bundled.
for app_chunk in NEW_APP.chunks(4096) {
    ota.write(app_chunk)?;
}

// Performs validation of the newly written app image and completes the OTA update.
let mut completed_ota = ota.finalize()?;

// Sets the newly written to partition as the next partition to boot from.
completed_ota.set_as_boot_partition()?;
// Restarts the CPU, booting into the newly written app.
completed_ota.restart();

如果启用了回滚功能,您需要验证新应用程序是否按预期工作,或者执行回滚。请参阅Espressif文档中的更多信息,了解应用程序回滚

fn main() {
    if is_working_as_intended() {
        esp_ota::mark_app_valid();
    } else {
        esp_ota::rollback_and_reboot().expect("Failed to roll back to working app");
    }
}

依赖项

~2–10MB
~103K SLoC