uploaded 1 week ago
Provide extra bootloader support, now support upgrading the firmware by decompressing the OTA firmware in the bootloader stage.

readme (zh)

# bootloader support plus

[![Component Registry](https://components.espressif.com/components/espressif/bootloader_support_plus/badge.svg)](https://components.espressif.com/components/espressif/bootloader_support_plus)

  * [English Version](https://github.com/espressif/esp-iot-solution/blob/master/components/bootloader_support_plus/README.md)

  ## 概述
bootloader support plus 是乐鑫基于 [ESP-IDF](https://github.com/espressif/esp-idf) 的 [custom_bootloader](https://github.com/espressif/esp-idf/tree/master/examples/custom_bootloader)  推出的增强版 bootloader,支持在 bootloader 阶段对`压缩`的固件进行 `解压缩`,来升级原有固件。在该方案中,您可以直接使用 ESP-IDF 中原生的 OTA 接口(比如 [esp_ota](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/ota.html#api-reference)、[esp_https_ota](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_https_ota.html#api-reference))。下表总结了适配 `bootloader support plus` 的乐鑫芯片以及其对应的 ESP-IDF 版本:

| Chip     | ESP-IDF Release/v5.0                                         | ESP-IDF Release/v5.1                                  |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| ESP32-C3 | [![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e) | [![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e) |
| ESP32-C2 | [![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e) | [![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e) |
| ESP32 | [![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e) |[![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)|
| ESP32C6 | N/A |[![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)|
| ESP32H2 | N/A |[![alt text](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)](https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e)|

## 压缩率

| Chip     | Demo            | Original firmware size(Bytes) | Compressed firmware size(Bytes) | Compression ratio(%) |
| -------- | --------------- | ----------------------------- | ------------------------------- | -------------------- |
| ESP32-C3 | hello_world     | 156469                        | 75140                           | 51.98%               |
| ESP32-C3 | esp_http_client | 954000                        | 502368                          | 47.34%               |
| ESP32-C3 | wifi_prov_mgr   | 1026928                       | 512324                          | 50.11%               |

上述示例都是在 ESP-IDF Tag/v5.0 上编译的。

其中压缩率是指`Original_firmware_size-Compressed_firmware_size)/Original_firmware_size)`,因此压缩率越大代表生成的压缩固件的体积越小。大部分情况下,压缩率在 40%~60%。因此,存放压缩固件的分区的大小可以预留为存放正常的固件分区大小的 60%。

## 优势

- 节省硬件 flash 空间。压缩后的固件体积更小,因此需要的存储空间更小。例如原始固件大小为 1MB,如果使用全量更新,则必须使用两个 1MB 大小的分区。此时,你需要使用一个 4MB 大小的 flash。使用压缩 OTA 时,您可以设置一个大小为 1MB 的分区和一个大小为 640KB 的分区。 现在您可以使用 2MB 大小的 flash 来完成您的项目。

    ```
        ****************               ****************
        * ota_0 (1M)  *               * ota_0 (1M)   *
        ****************               ****************
        * ota_1 (1M)   *               * ota_1 (640KB)*
        ****************               ****************
           (全量更新)                       (压缩更新)
    ```

- 节省传输时间,提高更新成功率。部署在带宽受限,网络环境差的设备,可能因设备掉线、传输的固件数据大导致更新成功率低,传输时间长。压缩更新缩短传输固件所需的时间,提高更新成功率。
- 节省传输流量。压缩后的固件的体积更小,因此传输需要的流量更小。对流量计费的设备将节省维护成本。  
- 节省 OTA 功耗。测试表明,一次 OTA 过程中,传输固件数据所消耗的能源超过总的能源消耗的 80% ,因此传输的数据量越小,越节省功耗。
- 不需要新增任何 API。该方案支持 ESP-IDF 中原生的 OTA 接口,如 [esp_ota](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/ota.html#api-reference)、[esp_https_ota](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_https_ota.html#api-reference) 。
- 兼容 Secure Boot 和 flash 加密方案。

## 如何使用bootloader support plus

为了使用压缩更新,您需要进行以下更改:

1. 请参阅 [bootloader override example](https://github.com/espressif/esp-idf/tree/master/examples/custom_bootloader/bootloader_override) 在工程中添加 `bootloader_components` 目录。

2. 在 `bootloader_components` 目录中创建 idf_component.yml 文件。

      ```yaml
      dependencies:
        espressif/bootloader_support_plus: ">=0.1.0"
      ```

3. 在 `bootloader_components/main/bootloader_start.c` 中添加头文件 `bootloader_custom_ota.h` 。

   ```
   #if defined(CONFIG_BOOTLOADER_COMPRESSED_ENABLED)
   #include "bootloader_custom_ota.h"
   #endif
   ```

4. 在 `bootloader_components/mian/bootloader_start.c` 中调用 `bootloader.custom_ota_main()`:

   ```c
   ...
   bootloader_state_t bs = {0};
   int boot_index = select_partition_number(&bs);
   if (boot_index == INVALID_INDEX) {
       bootloader_reset();
   }
   #if defined(CONFIG_BOOTLOADER_COMPRESSED_ENABLED)
       // 2.1 Call custom OTA routine
       boot_index = bootloader_custom_ota_main(&bs, boot_index);
   #endif
   ```

5. 添加 `bootloader_support_plus` 组件。你可以通过 `idf.py add-dependancy`, 命令添加该组件,如:

   ```shell
   idf.py add-dependency "espressif/bootloader_support_plus=*"
   ```

   可选地,你也可以在当前工程的 main 目录中通过创建一个 idf_component.yml 文件,然后添加下面的内容来添加该组件.

   ```yaml
   dependencies:
     espressif/bootloader_support_plus: ">=0.1.0"
   ```

   关于组件管理器的更多说明请参考 [Espressif's documentation](https://docs.espressif.com/projects/idf-component-manager/en/latest/index.html)。

6. 创建支持压缩更新的分区表。默认情况下,分区表中类型为 `app` 的最后一个分区用作存储压缩固件的分区。因为压缩固件的大小将小于原始固件的大小,所以可以将该分区设置得更小。下述为压缩更新中使用到的一个典型的分区表示例:

      ```
      # Name,   Type, SubType, Offset,   Size, Flags
      phy_init, data, phy,       ,        4k
      nvs,      data, nvs,       ,        28k
      otadata,  data, ota,       ,        8k
      ota_0,    app,  ota_0,     ,        1216k,
      ota_1,    app,  ota_1,     ,        640k,
      ```

7. 在工程目录中通过  `idf.py menuconfig -> Bootloader config (Custom) -> Enable compressed OTA support` 使能压缩更新的支持。

## 如何生成压缩固件

通过 [cmake_utilites](https://components.espressif.com/components/espressif/cmake_utilities) 组件可以制作压缩的固件。在添加该组件后,你可以通过运行下述命令来生成压缩的固件:

```
idf.py gen_compressed_ota
```

在工程目录中运行上述命令将在当前目录中生成 `build/custom_ota_binaries/app_name.bin.xz.packed`。其中 `app_name.bin.xz.packed` 文件就是要传输的压缩固件。有关制作压缩固件的更多说明你还可以参考 [Gen Compressed OTA](https://github.com/espressif/esp-iot-solution/blob/master/tools/cmake_utilities/docs/gen_compressed_ota.md) 。

## 示例

在 esp-iot-solution 中有一个参考示例:[ota/simple_ota_example](https://github.com/espressif/esp-iot-solution/tree/master/examples/ota/simple_ota_example) 。

您可以通过以下命令从此示例创建项目:

```
idf.py create-project-from-example "espressif/bootloader_support_plus=*:simple_ota_example"
```

## 注意

1. 当使用压缩更新时,双分区情况下,不支持版本回滚。
   当您的 flash 分区仅有一个存储 app 的分区,和一个存储压缩固件的分区时,压缩更新将无法提供版本回滚的功能,请在下发压缩固件前验证压缩固件的可用性和正确性。
2. 当启用 secure boot 和 flash 加密时,存储压缩固件的分区的大小 > (压缩固件的大小 + 8KB)。

### Q&A

Q1. 在使用包管理器的时候遇到了如下问题:

```
Executing action: create-project-from-example
CMakeLists.txt not found in project directory /home/username             
```

A1. 这是旧版本的包管理器中存在的兼容性问题, 请在您的 ESP-IDF 开发环境中运行 `pip install -U idf-component-manager` 命令来更新包管理器组件。

Q2. 已经使用 esp bootloader plus 方案的设备,是否可以使用 bootloader support plus 方案?

A2. 可以。您可以使用脚本工具 [gen_custom_ota.py](https://github.com/espressif/esp-iot-solution/blob/master/tools/cmake_utilities/scripts/gen_custom_ota.py) 来执行下述命令生成适用于esp bootloader plus 方案的压缩固件:

```
python3 gen_custom_ota.py -hv v2 -i simple_ota.bin
```

另外,因为这两个方案采取不同的文件格式以及不同的触发更新的机制,请确保已经使用 esp bootloader plus 方案的设备继续使用包含 SubType 为 0x22 的 storage 分区的分区表:

```
# Name,   Type, SubType, Offset,   Size, Flags
phy_init, data, phy, 0xf000,        4k
nvs,      data, nvs,       ,        28k
otadata,  data, ota,       ,        8k
ota_0,    app,  ota_0,     ,        1216k,
storage,  data, 0x22,      ,        640k,
```

然后在 menuconfig 配置菜单中使能 `CONDIF_ENABLE_LEGACY_ESP_BOOTLOADER_PLUS_V2_SUPPORT` 选项。

最后您只需要将压缩固件下载到 storage 分区,然后重启设备即可触发更新。

## 贡献
我们欢迎以错误报告、功能请求和拉取请求的形式对此项目做出贡献。

您可以使用 Github Issues 提交问题报告和功能请求:https://github.com/espressif/esp-iot-solution/issues。 在打开新的 issue 之前,请检查该问题是否已经被上报。

您可以发起一个 Pull Request 来提交您的代码。提交代码应遵循 ESP-IDF 项目的[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/contribute/index.html)。 

Links

License: Apache-2.0

To add this component to your project, run:

idf.py add-dependency "espressif/bootloader_support_plus^0.2.4"

or download archive

Dependencies

  • espressif/cmake_utilities 0.*
  • ESP-IDF >=5.0
  • espressif/xz 1.*
  • Examples:

    simple_ota_example

    more details

    To create a project from this example, run:

    idf.py create-project-from-example "espressif/bootloader_support_plus^0.2.4:simple_ota_example"

    or download archive (219 bytes)

    Stats

    • Archive size
      Archive size: 33.46 KB
    • Downloaded in total
      Downloaded in total 16.2k times
    • Downloaded this version
      This version: 67 times

    Badge

    espressif/bootloader_support_plus version: 0.2.4
    |