# Bootloader

DepthAI Bootloader 是一个小型程序，负责处理启动过程，要么启动已刷入的应用（参见 [独立模式](https://docs.luxonis.com/software/depthai/standalone.md)）， 要么初始化 OAK PoE
相机，使 DepthAI API 能够连接。OAK PoE 相机出厂时已带有工厂刷入的 bootloader。

Bootloader 捆绑在 depthai 库中，因此例如要刷入最新的 bootloader，应使用最新的 depthai 库。

## 设备管理器

device_manager.py 是一个 Python 脚本，用于与设备的 Bootloader 及 bootloader 配置进行交互。 它位于
[depthai-python/utilities](https://github.com/luxonis/depthai-python/tree/main/utilities)。

### 关于设备

允许您选择要连接的设备，并查看已连接设备的元数据。

 * 首先，我们必须选择要连接（启动）的设备，可通过以下方式选择：
   
   * 下拉菜单 包含已发现的设备 MX Id。下拉菜单仅在启动应用时更新。
   * 指定 IP 按钮（如果您的 OAK PoE 相机不在同一局域网内）。
   * 搜索 功能——将打开一个新窗口，显示一个表格，包含所有可用摄像头（通过 USB 端口或局域网——OAK PoE），以及它们的 MxId、名称和状态。点击表格行将选择该设备并启动至该设备。

### 配置设置

选择具有已刷入 bootloader 的设备后，您还可以配置 bootloader 配置。

 * 如果设备 已刷入网络 bootloader，您将能够设置其静态/动态 IP、掩码、网关、DNS、MAC 等。
 * 如果设备 已刷入 USB bootloader，您将能够设置其 USB 最大速度和 USB 超时。

设置一些值后，您必须点击 Flash configuration 按钮。您还可以 Clear configuration 或 View configuration（其 JSON）。

### 应用设置

在处理 [独立模式](https://docs.luxonis.com/software/depthai/standalone.md) 应用时有用。

 * 刷写应用：选择要刷写设备的 DepthAI 应用包（.dap）。以下代码片段展示了如何创建 dap 文件。
 * 移除应用：从设备中移除/清除已刷写的应用。
 * 打开设备流式传输应用：开始从设备上所有已连接的摄像头流式传输帧。

```python
import depthai as dai
pipeline = dai.Pipeline()
# ... 向管道添加节点
dai.DeviceBootloader.saveDepthaiApplicationPackage(
    './file.dap', # 保存 .dap 文件的位置
    pipeline, # 我的管道
    compress=True, # 压缩固件和资源。在我的案例中，从 24MB 压缩至 9.5MB
    applicationName='myAppName' # 可选，以便后续知道刷写了哪个应用
  )
```

## 危险区域

> **软砖**
> 本部分可能导致设备软砖，请谨慎使用。

以下是更新 bootloader 的视频教程：

为了防止软砖，OAK 设备（自 2023 年起）具有工厂 bootloader 和用户 bootloader。如果用户刷写了损坏的用户 bootloader，它将回退到使用工厂 bootloader。更新 bootloader 时， 设备管理器将尝试先刷写用户
bootloader（如果已刷写的工厂 bootloader 支持）。如果不可行，它将刷写工厂 bootloader。

 * 更新 Bootloader 按钮将刷写最新的 bootloader 到设备。您可以选择 AUTO、USB 或 NETWORK bootloader。
   
   * AUTO 将选择相机当前连接的 bootloader 连接类型。如果您通过 USB 连接到 OAK PoE 相机（进行恢复出厂设置），则不应选择 AUTO，因为它会刷写 USB bootloader。
   * USB bootloader 将尝试启动存储在闪存中的应用程序。如果找不到已刷写的应用程序，它将作为普通 USB OAK 运行——等待主机计算机初始化应用程序。
   * NETWORK bootloader 用于 OAK PoE 相机，并在工厂刷写。它处理网络初始化，以便 OAK PoE 相机可以通过 LAN 启动。

 * 刷写工厂 Bootloader：如果您想刷写工厂 bootloader，可以使用此按钮。即使已刷写用户 bootloader，它也会刷写工厂 bootloader。

 * 恢复出厂设置将擦除整个闪存内容，并仅重新刷写 USB 或 NETWORK bootloader。已刷写的应用程序（管道、资源）和 bootloader 配置将丢失。

 * 启动至 USB 恢复模式将强制例如 OAK PoE 相机通过 USB 连接器可用，即使其启动引脚设置为 PoE 启动。这主要由我们的固件开发人员使用。

### 工厂启动加载器与用户启动加载器

启动加载器分为两类：

 * 工厂启动加载器：在工厂中刷写的启动加载器。不建议重新刷写此启动加载器，因为它不打算由最终用户编辑。
 * 用户启动加载器：可由用户刷写的启动加载器。如果启动失败（例如刷写时损坏），则会回退到工厂启动加载器。

USB 设备不支持用户启动加载器。如果设备具有用户启动加载器，则默认使用它。如果用户启动加载器未刷写，则会回退到工厂启动加载器。

## 启动开关

 * 从闪存启动 - DIP 开关：0x03（开关 5、6 打开）- 适用于已安装启动加载器的 OAK PoE 和 USB 相机。
 * USB 恢复模式 - DIP 开关：0x16（开关 2、4、5 打开）- 直接启动进入 USB 模式，使相机等待主机通过 USB 连接。

在较新版本的 OAK 设备中，我们使用 0 欧姆电阻（见下图）代替 DIP 开关，这意味着 OAK
将默认从闪存启动。这些新设备已刷写启动加载器，负责处理启动过程。基板上还有一个额外的按钮，按下时可将启动切换到恢复模式，这在启动加载器尚未刷写时很有用（例如早期访问设备）。你需要在给设备通电时（启动发生时）按下此按钮。

## API

DeviceBootloader 是一个用于与启动加载器通信的类。它用于刷写创建的 [Pipeline](https://docs.luxonis.com/software/depthai-components/pipeline.md)、depthai
应用程序包或更新启动加载器本身。

```cpp
std::tuple<bool, std::string> flash(std::function<void(float)> progressCb, Pipeline& pipeline);

std::tuple<bool, std::string> flashDepthaiApplicationPackage(std::function<void(float)> progressCb, std::vector<uint8_t> package);

std::tuple<bool, std::string> flashBootloader(std::function<void(float)> progressCb, std::string path = "");
```

progressCb 参数接受一个回调函数，该函数将在每次进度更新时被调用（限速为 1 秒）。这主要用于通知用户当前的刷写进度。

### DepthAI 应用程序包（.dap）

DepthAI 应用程序包是一种二进制文件格式，用于存储数据段。此格式的目的是能够提取各个段并进行 OTA 更新，而无需更新所有数据。例如：在用户应用程序的更新 1 和更新 2 之间，Depthai 固件、资产存储（50MiB
神经网络）和资产结构保持不变，但一些处理节点被添加到管线中。此时无需传输整个包，只需发送和更新管线描述即可。

DepthAI 应用程序包（.dap）包含：

 * SBR（512B 头部，描述数据段）
 * Depthai 设备固件（段 "__firmware"）
 * 管线描述（段 "pipeline"）
 * 资产结构（段 "assets"）
 * 资产存储（段 "asset_storage"）

## MAC 地址

所有 OAK PoE 相机都有一个唯一的 MAC 地址，用于在网络中标识设备。它是根据设备的 MxID
计算得出的，详见[逻辑](https://gist.github.com/Erol444/85d6ef7ae9c946f5688854b86c548dc7)。MAC 地址存储在 DeviceBootloader 配置中。
