# 烧录 USB 恢复启动引导头

此脚本将特殊的 USB“恢复引导头”烧录到设备的板载闪存中。

> **引导头**
> 脚本允许烧录不同的引导头。此示例仅关注 USB 恢复引导头，因为其他引导头不常用。

某些设备，例如 [OAK-FFC 4P](https://docs.luxonis.com/hardware/products/OAK-FFC%25204P.md)，可以烧录引导加载程序。写入 USB 恢复引导头后，设备将不再使用引导加载程序，而是像标准
USB 设备（类似于 OAK-1）一样启动。

在以下场景中，这可能非常有用：

 * 消除引导加载程序在空闲模式下的额外功耗
 * 恢复到简单的纯 USB 设置，去除高级引导加载程序功能

> 覆盖引导加载程序意味着设备不再支持高级引导加载程序功能。请仅在了解相关影响的情况下执行此操作。此操作可以通过重新烧录引导加载程序来恢复。

## 演示

示例脚本可能输出如下内容：

```bash
~/depthai-python/examples$ python3 flash_boot_header.py USB_RECOVERY
Found device with name: 1.1
Successfully flashed boot header!
```

## 设置

请运行[安装脚本](https://github.com/luxonis/depthai-python/blob/main/examples/install_requirements.py)以下载所有必需的依赖项。请注意，此脚本必须在 git
上下文中运行，因此您需要先下载 [depthai-python](https://github.com/luxonis/depthai-python) 仓库，然后运行该脚本。

```bash
git clone https://github.com/luxonis/depthai-python.git
cd depthai-python/examples
python3 install_requirements.py
```

更多信息，请参考[安装指南](https://docs.luxonis.com/software/depthai/manual-install.md)。

## 源代码

#### Python

```python
import sys
from typing import Callable, Tuple
from enum import Enum
import depthai

FLASH = depthai.DeviceBootloader.Memory.FLASH

def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} [GPIO_MODE/USB_RECOVERY/NORMAL/FAST] [params]")
        print("\tOptions:")
        print(f"\t\t{sys.argv[0]} GPIO_MODE gpioModeNum")
        print(f"\t\t{sys.argv[0]} USB_RECOVERY")
        print(f"\t\t{sys.argv[0]} NORMAL [frequency] [location] [dummyCycles] [offset]")
        print(f"\t\t{sys.argv[0]} FAST [frequency] [location] [dummyCycles] [offset]")
        return 0

    mode = sys.argv[1].lower()
    flash_func = None

    if mode == "gpio_mode":
        # gpio mode header
        if len(sys.argv) < 3:
            print(f"Usage: {sys.argv[0]} GPIO_MODE gpioModeNum")
            return 0
        
        gpio_mode = int(sys.argv[2])
        def flash_gpio(bl: 'depthai.DeviceBootloader') -> Tuple[bool, str]:
            return bl.flashGpioModeBootHeader(FLASH, gpio_mode)
        flash_func = flash_gpio

    elif mode == "usb_recovery":
        # usb recovery header
        def flash_usb(bl: 'depthai.DeviceBootloader') -> Tuple[bool, str]:
            return bl.flashUsbRecoveryBootHeader(FLASH)
        flash_func = flash_usb

    elif mode in ("normal", "fast"):
        if len(sys.argv) != 2 and len(sys.argv) != 3 and len(sys.argv) <= 3:
            print(f"Usage: {sys.argv[0]} NORMAL/FAST [frequency] [location] [dummyCycles] [offset]")
            print(f"Usage: {sys.argv[0]} NORMAL/FAST [frequency]")
            return 0

        offset = -1
        location = -1
        dummy_cycles = -1
        frequency = -1

        if len(sys.argv) > 3:
            if len(sys.argv) >= 3:
                offset = int(sys.argv[2])
            if len(sys.argv) >= 4:
                location = int(sys.argv[3])
            if len(sys.argv) >= 5:
                dummy_cycles = int(sys.argv[4])
            if len(sys.argv) >= 6:
                frequency = int(sys.argv[5])
        elif len(sys.argv) == 3:
            frequency = int(sys.argv[2])

        if mode == "normal":
            def flash_normal(bl: 'depthai.DeviceBootloader') -> Tuple[bool, str]:
                return bl.flashBootHeader(FLASH, frequency, location, dummy_cycles, offset)
            flash_func = flash_normal
        elif mode == "fast":
            def flash_fast(bl: 'depthai.DeviceBootloader') -> Tuple[bool, str]:
                return bl.flashFastBootHeader(FLASH, frequency, location, dummy_cycles, offset)
            flash_func = flash_fast

    # Find device and flash specified boot header
    success, info = depthai.DeviceBootloader.getFirstAvailableDevice()
    
    if success:
        print(f"Found device with name: {info.name}")
        bl = depthai.DeviceBootloader(info)

        # Flash the specified boot header
        if flash_func:
            success, error_msg = flash_func(bl)
            if success:
                print("Successfully flashed boot header!")
            else:
                print(f"Couldn't flash boot header: {error_msg}")
        else:
            print("Invalid boot option header specified")
    else:
        print("No devices found")

    return 0

if __name__ == "__main__":
    main()
```

#### C++

```cpp
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <string>

#include "depthai/depthai.hpp"

int main(int argc, char** argv) {
    if(argc < 2) {
        std::cout << "Usage: " << argv[0] << " [GPIO_MODE/USB_RECOVERY/NORMAL/FAST] [params]" << std::endl;
        std::cout << "\tOptions:\n";
        std::cout << "\t\t" << argv[0] << " GPIO_MODE gpioModeNum" << std::endl;
        std::cout << "\t\t" << argv[0] << " USB_RECOVERY" << std::endl;
        std::cout << "\t\t" << argv[0] << " NORMAL [frequency] [location] [dummyCycles] [offset]" << std::endl;
        std::cout << "\t\t" << argv[0] << " FAST [frequency] [location] [dummyCycles] [offset]" << std::endl;
        return 0;
    }
    std::string mode{argv[1]};
    std::transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
    std::function<std::tuple<bool, std::string>(dai::DeviceBootloader&)> flash = nullptr;

    if(mode == "gpio_mode") {
        // gpio mode header
        if(argc < 3) {
            std::cout << "Usage: " << argv[0] << " GPIO_MODE gpioModeNum" << std::endl;
            return 0;
        }
        int gpioMode = std::stoi(std::string(argv[2]));

        flash = [gpioMode](dai::DeviceBootloader& bl) { return bl.flashGpioModeBootHeader(dai::DeviceBootloader::Memory::FLASH, gpioMode); };
    } else if(mode == "usb_recovery") {
        // usb recovery header
        flash = [](dai::DeviceBootloader& bl) { return bl.flashUsbRecoveryBootHeader(dai::DeviceBootloader::Memory::FLASH); };
    } else if(mode == "normal" || mode == "fast") {
        if(argc != 2 && argc != 3 && argc <= 3) {
            std::cout << "Usage: " << argv[0] << " NORMAL/FAST [frequency] [location] [dummyCycles] [offset]" << std::endl;
            std::cout << "Usage: " << argv[0] << " NORMAL/FAST [frequency]" << std::endl;
            return 0;
        }
        int64_t offset = -1;
        int64_t location = -1;
        int32_t dummyCycles = -1;
        int32_t frequency = -1;
        if(argc > 3) {
            if(argc >= 3) {
                offset = std::stoi(std::string(argv[2]));
            }
            if(argc >= 4) {
                location = std::stoi(std::string(argv[3]));
            }
            if(argc >= 5) {
                dummyCycles = std::stoi(std::string(argv[4]));
            }
            if(argc >= 6) {
                frequency = std::stoi(std::string(argv[5]));
            }
        } else if(argc == 3) {
            frequency = std::stoi(std::string(argv[2]));
        }

        if(mode == "normal") {
            flash = [offset, location, dummyCycles, frequency](dai::DeviceBootloader& bl) {
                return bl.flashBootHeader(dai::DeviceBootloader::Memory::FLASH, frequency, location, dummyCycles, offset);
            };
        } else if(mode == "fast") {
            flash = [offset, location, dummyCycles, frequency](dai::DeviceBootloader& bl) {
                return bl.flashFastBootHeader(dai::DeviceBootloader::Memory::FLASH, frequency, location, dummyCycles, offset);
            };
        }
    }

    // Find device and flash specified boot header
    bool res = false;
    dai::DeviceInfo info;
    std::tie(res, info) = dai::DeviceBootloader::getFirstAvailableDevice();

    if(res) {
        std::cout << "Found device with name: " << info.name << std::endl;
        dai::DeviceBootloader bl(info);
        // Flash the specified boot header
        if(flash) {
            bool success;
            std::string errorMsg;
            std::tie(success, errorMsg) = flash(bl);
            if(success) {
                std::cout << "Successfully flashed boot header!" << std::endl;
            } else {
                std::cout << "Couldn't flash boot header: " << errorMsg << std::endl;
            }
        } else {
            std::cout << "Invalid boot option header specified" << std::endl;
        }
    } else {
        std::cout << "No devices found" << std::endl;
    }

    return 0;
}
```

### 需要帮助？

请前往 [OAKChina 官网](https://www.oakchina.cn/) 获取技术支持或解答您的任何疑问。
