量产程序
=====================

:link_to_translation:`en:[English]`

介绍
------------

这一程序主要用于量产时为每一设备创建工厂 NVS（非易失性存储器）分区镜像。NVS 分区镜像由 CSV（逗号分隔值）文件生成，文件中包含了用户提供的配置项及配置值。

注意，该程序仅创建用于量产的二进制镜像，您需要使用以下工具将镜像烧录到设备上：

- `esptool.py`_
- `Flash 下载工具 <https://www.espressif.com/en/support/download/other-tools?keys=flash+download+tools>`_ （仅适用于 Windows）。下载后解压，然后按照 doc 文件夹中的说明操作。
- 使用定制的生产工具直接烧录程序


准备工作
-------------

**该程序依赖于 esp-idf 的 NVS 分区程序**

* 操作系统要求：
    -   Linux、MacOS 或 Windows（标准版）

* 安装依赖包：
    -   `Python <https://www.python.org/downloads/>`_

.. note::

    使用该程序之前，请确保：
        - Python 路径已添加到 PATH 环境变量中；
        - 已经安装 `requirement.txt` 中的软件包，`requirement.txt` 在 esp-idf 根目录下。


具体流程
-----------

.. blockdiag::

    blockdiag {
    A [label = "CSV 配置文件"];
    B [label = "主 CSV 文件"];
    C [label = "二进制 bin 文件", stacked];

    A -- B -> C
    }


CSV 配置文件
----------------------

CSV 配置文件中包含设备待烧录的配置信息，定义了待烧录的配置项。

配置文件中数据格式如下（`REPEAT` 标签可选）::

       name1,namespace,    <-- 第一个条目应该为 "namespace" 类型
       key1,type1,encoding1
       key2,type2,encoding2,REPEAT
       name2,namespace,
       key3,type3,encoding3
       key4,type4,encoding4

.. note:: 文件第一行应始终为 ``namespace`` 条目。

每行应包含三个参数：``key``、``type`` 和 ``encoding``，并以逗号分隔。
如果有 ``REPEAT`` 标签，则主 CSV 文件中所有设备此键值均相同。

*有关各个参数的详细说明，请参阅 NVS 分区生成程序的 README 文件。*

CSV 配置文件示例如下::

	app,namespace,
	firmware_key,data,hex2bin
	serial_no,data,string,REPEAT
	device_no,data,i32


.. note::

    请确保：
        - 逗号 ',' 前后无空格；
        - CSV 文件每行末尾无空格。


主 CSV 文件
---------------------

主 CSV 文件中包含设备待烧录的详细信息，文件中每行均对应一个设备实体。

主 CSV 文件的数据格式如下::

	key1,key2,key3,.....
	value1,value2,value3,....

.. note:: 文件中键 (``key``) 名应始终置于文件首行。从配置文件中获取的键，在此文件中的排列顺序应与其在配置文件中的排列顺序相同。主 CSV 文件同时可以包含其它列（键），这些列将被视为元数据，而不会编译进最终二进制文件。

每行应包含相应键的键值 (``value``) ，并用逗号隔开。如果某键带有 ``REPEAT`` 标签，则仅需在第二行（即第一个条目）输入对应的值，后面其他行为空。

参数描述如下：

``value``
    Data value

``value`` 是与键对应的键值。

主 CSV 文件示例如下::

	id,firmware_key,serial_no,device_no
	1,1a2b3c4d5e6faabb,A1,101
	2,1a2b3c4d5e6fccdd,,102
	3,1a2b3c4d5e6feeff,,103

.. note:: 如果出现 `REPEAT` 标签，则会在相同目录下生成一个新的主 CSV 文件用作主输入文件，并在每行为带有 `REPEAT` 标签的键插入键值。

量产程序还会创建中间 CSV 文件，NVS 分区程序将使用此 CSV 文件作为输入，然后生成二进制文件。

中间 CSV 文件的格式如下::

	key,type,encoding,value
	key,namespace, ,
	key1,type1,encoding1,value1
	key2,type2,encoding2,value2

此步骤将为每一设备生成一个中间 CSV 文件。


运行量产程序
-------------------

**使用方法**::

        python mfg_gen.py [-h] {generate,generate-key} ...

**可选参数**：

+------+------------+----------------------+
| 序号 |    参数    |         描述         |
+------+------------+----------------------+
|   1  | -h, --help | 显示帮助信息并退出   |
+------+------------+----------------------+

**命令**：

运行 mfg_gen.py {command} -h 查看更多帮助信息

+------+--------------+---------------+
| 序号 |     参数     |      描述     |
+------+--------------+---------------+
|   1  |   generate   | 生成 NVS 分区 |
+------+--------------+---------------+
|   2  | generate-key |  生成加密密钥 |
+------+--------------+---------------+

**为每个设备生成工厂镜像（默认）**

**使用方法**::

        python mfg_gen.py generate [-h] [--fileid FILEID] [--version {1,2}] [--keygen]
                                        [--keyfile KEYFILE] [--inputkey INPUTKEY]
                                        [--outdir OUTDIR]
                                        conf values prefix size

**位置参数**：

+--------+--------------------------------------------------+
|  参数  |                       描述                       |
+--------+--------------------------------------------------+
| conf   | 待解析的 CSV 配置文件路径                        |
+--------+--------------------------------------------------+
| values | 待解析的主 CSV 文件路径                          |
+--------+--------------------------------------------------+
| prefix | 每个输出文件名前缀的唯一名称                     |
+--------+--------------------------------------------------+
| size   | NVS 分区大小（以字节为单位，且为 4096 的整数倍） |
+--------+--------------------------------------------------+


**可选参数**：

+---------------------+--------------------------------------------------------------------------------+
|         参数        |                                      描述                                      |
+---------------------+--------------------------------------------------------------------------------+
| -h, --help          | 显示帮助信息并退出                                                             |
+---------------------+--------------------------------------------------------------------------------+
| --fileid FILEID     | 每个文件名后缀的唯一文件标识符（主 CSV 文件中的任意键），默认为数值 1、2、3... |
+---------------------+--------------------------------------------------------------------------------+
| --version {1,2}     | - 设置多页 Blob 版本。                                                         |
|                     | - 版本 1 - 禁用多页 Blob；                                                     |
|                     | - 版本 2 - 启用多页 Blob；                                                     |
|                     | - 默认版本：版本 2                                                             |
+---------------------+--------------------------------------------------------------------------------+
| --keygen            | 生成 NVS 分区加密密钥                                                          |
+---------------------+--------------------------------------------------------------------------------+
| --inputkey INPUTKEY | 内含 NVS 分区加密密钥的文件                                                    |
+---------------------+--------------------------------------------------------------------------------+
| --outdir OUTDIR     | 输出目录，用于存储创建的文件（默认当前目录）                                   |
+---------------------+--------------------------------------------------------------------------------+



请运行以下命令为每个设备生成工厂镜像，量产程序同时提供了一个 CSV 示例文件::

    python mfg_gen.py generate samples/sample_config.csv samples/sample_values_singlepage_blob.csv Sample 0x3000

主 CSV 文件应在 ``file`` 类型下设置一个相对路径，相对于运行该程序的当前目录。

**为每个设备生成工厂加密镜像**

运行以下命令为每一设备生成工厂加密镜像，量产程序同时提供了一个 CSV 示例文件。

- 通过量产程序生成加密密钥来进行加密::

    python mfg_gen.py generate samples/sample_config.csv samples/sample_values_singlepage_blob.csv Sample 0x3000 --keygen

.. note:: 创建的加密密钥格式为 ``<outdir>/keys/keys-<prefix>-<fileid>.bin``。加密密钥存储于新建文件的 ``keys/`` 目录下，与 NVS 密钥分区结构兼容。更多信息请参考 :ref:`nvs_encr_key_partition`。

- 提供加密密钥用作二进制输入文件来进行加密::

    python mfg_gen.py generate samples/sample_config.csv samples/sample_values_singlepage_blob.csv Sample 0x3000 --inputkey keys/sample_keys.bin

**仅生成加密密钥**

**使用方法**::

        python mfg_gen.py generate-key [-h] [--keyfile KEYFILE] [--outdir OUTDIR]

**可选参数：**
+-------------------+----------------------------------------------+
|        参数       |                     描述                     |
+-------------------+----------------------------------------------+
| -h, --help        | 显示帮助信息并退出                           |
+-------------------+----------------------------------------------+
| --keyfile KEYFILE | 加密密钥文件的输出路径                       |
+-------------------+----------------------------------------------+
| --outdir OUTDIR   | 输出目录，用于存储创建的文件（默认当前目录） |
+-------------------+----------------------------------------------+

运行以下命令仅生成加密密钥::

    python mfg_gen.py generate-key

.. note:: 创建的加密密钥格式为 ``<outdir>/keys/keys-<timestamp>.bin``。时间戳格式为：``%m-%d_%H-%M``。如需自定义目标文件名，请使用 --keyfile 参数。

生成的加密密钥二进制文件还可以用于为每个设备的工厂镜像加密。

``fileid`` 参数的默认值为 1、2、3...，与主 CSV 文件中的行一一对应，内含设备配置值。

运行量产程序时，将在指定的 ``outdir`` 目录下创建以下文件夹：

- ``bin/`` 存储生成的二进制文件
- ``csv/`` 存储生成的中间 CSV 文件
- ``keys/`` 存储加密密钥（创建工厂加密镜像时会用到）

.. _esptool.py: https://github.com/espressif/esptool/#readme
