# SDK tools for building and flashing images

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The QCC730 SDK provides the following Python script tools to help you build and flash images:

- qccsdk.py
- nvm\_programmer.py

## qccsdk.py

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The qccsdk.py script file is in the .\qccsdk folder.

The following tables list the parameters of the qccsdk.py script file.

Table : qccsdk.py set parameters

| Parameter | Description |
| --- | --- |
| --help | Print help messages |
| -b (--board) | Board type:<br><ul class="ul" id="qccsdk_py__ul_zcn_xmy_w1c"><br>                                <li class="li"><em class="ph i">mqm730i</em> for iPA</li><br><br>                                <li class="li"><em class="ph i">mqm730x</em> for xPA</li><br><br>                            </ul> |
| -S | Sample:<br><ul class="ul" id="qccsdk_py__ul_adn_xmy_w1c"><br>                                <li class="li"><em class="ph i">demo/qcli_demo</em> for QCLI_DEMO</li><br><br>                                <li class="li"><em class="ph i">ftm</em> for FTM mode</li><br><br>                                <li class="li"><em class="ph i">sbl</em> for SBL</li><br><br>                                <li class="li"><em class="ph i">prg</em> for NVM Programmer, which is used for downloading images</li><br><br>                            </ul> |
| -o | Output directory (relative path) |
| --jtag | Set JTAG interface type: &lt;openocd/jlink&gt; |
| --menuconfig | Set Kconfig manually |
| --verbose | Enable output debug info on console |

Table : qccsdk.py build parameters

| Parameter | Description |
| --- | --- |
| --help | Print help messages |
| --build<br><br><br>                            <br>(default) | Build to generate images |
| --clean | Clean build |
| --rebuild | Clean then build |
| --verbose | Enable output debug info on console |

Table : qccsdk.py flash parameters

| Parameter | Description |
| --- | --- |
| --help | Print help messages |
| --flash<br><br><br>                            <br>(default) | Flash images |
| --reset | Reset the board after flash |
| --erase | Erase all RRAM and flash |
| --verbose | Enable output debug info on console |
| --bdf | Flash board data |

### qccsdk.py command examples

**Build images**

The following examples demonstrate how to build QCC730 images for the iPA version of QCC730M. To build images for the xPA version, use the `-b=mqm730x` parameter in the related commands.

- Build the QCLI\_DEMO image

    Use the following commands to build the QCLI\_DEMO image for QCC730:

        python qccsdk.py set -b=mqm730i
        python qccsdk.py set -S=demo/qcli_demo
        python qccsdk.py build --rebuildCopy to clipboard

    Or

        python qccsdk.py set -S=demo/qcli_demo -b=mqm730i buildCopy to clipboard

    By default, the generated image is in the following directory:

    .\qccsdk\output\mqm730i\FERMION\_IOE\_QCLI\_DEMO\DEBUG\bin
- Build the SBL image

    Use the following command to build the SBL image for QCC730:

        python qccsdk.py set -S=sbl -b=mqm730i buildCopy to clipboard

    By default, the generated image is in the following directory:

    .\output\mqm730i\FERMION\_SBL\DEBUG\bin
- Build the PRG image

    Use the following command to build the NVM Programmer image for QCC730:

        python qccsdk.py set -S=prg -b=mqm730i buildCopy to clipboard

    By default, the generated image is in the following directory:

    .\output\mqm730i\FERMION\_NVM\_PROGRAMMER\DEBUG\bin

**Flash images**

You can flash all the five images (FDT, SBL\_A, SBL\_B, FWD, QCLI\_DEMO) to a QCC730 board by using the following command:

    python qccsdk.py flash --flash --resetCopy to clipboard

Note: 
                
OpenOCD is the default mode for flashing images. To use the J-Link interface, run the following command:

    qccsdk.py set --jtag=jlink Copy to clipboard

## QCC730 NVM Programmer

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The NVM Programmer loads PBL, SBL, and APP images onto the QCC730. On boards configured for development, factory test mode (FTM) or APP images can be programmed.

	
The location of the NVM Programmer is: qccsdk\tools\nvm\_programmer

### Image programming

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

### Basic usage

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The following syntaxes demonstrate the basic usages of NVM Programmer. In most situations, these syntaxes are sufficient for programming images and erasing or reading RRAM or flash.

### Invocation

- Program image to RRAM or
                    flash

        nvm_programmer.py -b ADDRESS -f file -n {rram,flash} -s {jlink,ch347}Copy to clipboard
- Program FDT, SBL, partition table, and app images in one
                    command

        nvm_programmer.py -s {jlink,ch347} -f file -P -ACopy to clipboard
- Partial erase RRAM or
                    flash

        nvm_programmer.py -b ADDRESS -S SIZE -e -n {rram,flash} -s {jlink,ch347}Copy to clipboard
- Chip erase flash

        nvm_programmer.py -E -n flash -s {jlink,ch347}Copy to clipboard
- Read data from RRAM or flash to a
                    file

        nvm_programmer.py -b ADDRESS -S SIZE -d -f file -n {rram,flash} -s {jlink,ch347}Copy to clipboard

### Arguments

Note that some arguments presented in [Table : Arguments for basic usage](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#nvm_basic_usage__table_nvm_basic_usage) have a short form (for example, -b) and a long form (for example,
                --begin\_address). The longer form is given inside parentheses; however, the two forms are functionally identical and are interchangeable.

Table : Arguments for basic usage

| Argument | Parameter | Purpose | Default Value |
| --- | --- | --- | --- |
| -b (--begin\_address) | ADDRESS | Specifies the starting address at which to program the image, partial erase or read flash/RRAM. | N/A |
| -f (--file) | FILE | Specifies the image file to be programmed or the file to store the read data from flash/RRAM. | N/A |
| -n (--nvm-name) | {rram,flash} | Specifies Non-Volatile Memory type name for which to operation, choices:{rram,flash}. | rram |
| -e (--partial\_erase) | N/A | Partial erase the RRAM or flash. | N/A |
| -S (--size) | SIZE | Indicates partial erase or read size. | N/A |
| -E (--chip\_erase) | N/A | Chip erase the flash. | N/A |
| -d (--read) | N/A | Read data from the RRAM or flash. | N/A |
| -s (--server) | {jlink,ch347} | Specifies the GDB server tool. | jlink |
| -i (--ram-image) | FILE | Specifies the programming image. | ..\bin\FERMION\_NVM\_PROGRAMMER.elf |

### Advanced usage

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The following usage syntax is intended for advanced users and isn't necessary for typical usage scenarios.

### Invocation

    nvm_programmer.py [-h] [-s {jlink,ch347}] [-p SERVER_PORT] [-path SERVER_PATH] [-script SERVER_SCRIPT] [--serial SERIAL] [-r | -R] 
    [-c CLIENT_EXE] [-u UDP_PORT] [-l CLIENT_LOG] [-f FILE] [-i RAM_IMAGE] [-b ADDRESS] [-n {rram,flash}] [-E] [-e] [-d] [-S SIZE]
    [-t TABLE][-P][-A][--reset]Copy to clipboard

### Arguments

Note that some arguments presented in [Table : Arguments for advanced usage](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#nvm_advanced_usage__table_nvm_adv_usage) have a short form (for example, -b) and a long form (for example, --begin\_address). The
                longer form is given inside parentheses. However, the two forms are functionally identical and are interchangeable.

Table : Arguments for advanced usage

| Argument | Parameter | Purpose | Default Value |
| --- | --- | --- | --- |
| -h (--help) | N/A | Shows the help screen. | N/A |
| -b (--begin\_address) | [ADDRESS] | Specifies the starting address at which to load the image, partial erase or read flash/RRAM. | N/A |
| -f (--file) | [FILE] | Used to specify the image file to be programmed or the file to store the read data from flash/RRAM. | N/A |
| -n (--nvm-name) | {rram,flash} | Specifies non-volatile memory (NVM) type name for which to operation, choices:{rram,flash}. | rram |
| -e (--partial\_erase) | N/A | Specifies NVM type name for which to operation, choices:{rram,flash}. | N/A |
| -S (--size) | [SIZE] | Indicates partial erase or read size. | N/A |
| -E (--chip\_erase) | N/A | Chip erase the flash. | N/A |
| -d (--read) | N/A | RRAM | N/A |
| -t (--table) | [TABLE] | Specifies XML file of download table to download images to flash/RRAM and erase flash/RRAM. | N/A |
| -P (--partition) | N/A | Program file to flash together with partition table and program FDT to RRAM. | N/A |
| -A (--all) | N/A | Program FDT, SBL, partition table and app all in once, can only be used with -P. | N/A |
| -s (--server) | {jlink,ch347} | Specifies the GDB server tool. | jlink |
| -p (--server-port) | [SERVER\_PORT] | Specifies the GDB server listening port. | 3333 |
| -c (--client-exe) | [CLIENT\_EXE] | Specifies the GDB client executable. | arm-none-eabi-gdb-py3.exe |
| -u (--udp-port) | [UDP\_PORT] | Specifies the UDP port for IPC traffic to the GDB client. | 19383 |
| -l (--client-log) | [CLIENT\_LOG] | Specifies the log file for the GDB client output. Use "stdout" to display to the console. | N/A |
| -i (--ram-image) | [RAM\_IMAGE] | Specifies the programming image. | The default image is: ..\bin\FERMION\_NVM\_PROGRAMMER.elf<br><br><br>                                <br>Each board should have a specified programming image, such as .\output\${boardName}\FERMION\_NVM\_PROGRAMMER\<br>                                    DEBUG\bin\FERMION\_NVM\_PROGRAMMER.elf. |
| --server-path | [SERVER\_PATH] | Specifies the path for JLinkGDBServerCL.exe or OpenOCD.exe.<br><br><br>                                <br>If not set, use OPENOCD\_PATH or JLINK\_PATCH environment variable. | N/A |
| --server-script | [SERVER\_SCRIPT] | Specifies the script file for JLinkGDBServerCL.exe or OpenOCD.exe. | jlink: qcc730.JLinkScript<br><br><br>                                <br>ch347: qcc730\_openocd\_ch347.cfg |
| --serial | [SERIAL] | Specifies the serial number (SN) of the J-Link to use. | N/A |
| -r (--start-server) | N/A | Start the GDB server as part of this script (default). | N/A |
| -R (--no-start-server) | N/A | This script shouldn't start the GDB server | N/A |
| --reset | N/A | Reset the target after program, erase or read. | N/A |

### Usage examples

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The following examples demonstrate how to flash a single image at a time. To prevent run failures, ensure that you flash all the mentioned images in either of the following groups.

	
**Commands for flashing FDT, SBL\_A, SBL\_B, and QCLI\_DEMO:**

		

    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x208000 -f ..\..\storage\firmware_desc_table\curr_age_fdt\frn_curr_age_default.bin
    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x20a400 -f ..\..\..\output\mqm730i\FERMION_SBL\DEBUG\bin\FERMION_SBL_HASHED.elf
    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x212400 -f ..\..\..\output\mqm730i\FERMION_SBL\DEBUG\bin\FERMION_SBL_HASHED.elf
    python nvm_programmer.py -s ch347 --nvm-name flash -b 0x043000 -P - f ..\..\..\output\mqm730i\FERMION_IOE_QCLI_DEMO\DEBUG\bin\FERMION_IOE_QCLI_DEMO_HASHED.elfCopy to clipboard

	
**Commands for flashing FDT, SBL\_A, SBL\_B, and FTM:**

		

    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x208000 -f ..\..\storage\firmware_desc_table\curr_age_fdt\frn_curr_age_with_app_bin.bin 
    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x20a400 -f ..\..\..\output\mqm730i\FERMION_SBL\DEBUG\bin\FERMION_SBL_HASHED.elf
    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x212400 -f ..\..\..\output\mqm730i\FERMION_SBL\DEBUG\bin\FERMION_SBL_HASHED.elf
    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x21A400 -f ..\..\..\output\mqm730i\FERMION_FTM\DEBUG\bin\FERMION_FTM.binCopy to clipboard

	
**Command for flashing BDF (flash it only if the board doesn't have BDF):**

		

    python nvm_programmer.py -s ch347 --nvm-name rram -b 0x37A000 -f ..\..\..\bin\wlan\mqm730i.binCopy to clipboard

	
Note: Image addresses (except for QCLI\_DEMO) are fixed. Don't change these addresses. The QCLI\_DEMO address may be modified if the configuration is different.

### OTP programming

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

Use the NVM Programmer to program the OTP memory.

### Invocation

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

nvm_programmer.py [-k KEY_CFG] [-g GET_KEY] [--config CONFIG] -n otp -s {jlink, ch347}Copy to clipboard

### Arguments

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

Most arguments presented in [Table : Arguments for OTP operation](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#otp_arguments__table_nvm_otp_arg) have a short form (for example, -k) and a long form (for example, --key-cfg). When both are
            present, the longer form is given inside parentheses. However, the two forms are functionally identical and are interchangeable.

Table : Arguments for OTP operation

| Argument | Parameter | Purpose | Default Value |
| --- | --- | --- | --- |
| -k (--key-cfg) | KEY\_CFG | One key-value pair of OTP field to program, supported OTP field is listed in [Table : OTP fields](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#otp_fields__table_otp_fields). | N/A |
| -g (--get-key) | GET\_KEY | The key of OTP field to read, supported OTP field is listed in [Table : OTP fields](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#otp_fields__table_otp_fields). | N/A |
| --config | CONFIG | The YAML file which may contain OTP key-value pairs, supported OTP field is listed in [Table : OTP fields](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#otp_fields__table_otp_fields). | N/A |
| -n (--nvm-name) | {otp} | Specifies the operation is for OTP | rram |
| -s (--server) | {jlink,ch347} | Specifies the GDB server tool. | Jlink |
| --compare-key | KEY\_CFG | One key-value pair to compare with that in the OTP region | N/A |

Note: 
            
Other arguments [**-p** SERVER\_PORT] [**--server-path** SERVER\_PATH] [**--server-script** SERVER\_SCRIPT] [**--serial** SERIAL] [**-r** | **-R**] [**-c** CLIENT\_EXE]
                    [**-u** UDP\_PORT] [**-l** CLIENT\_LOG] [**-f** FILE] [**-I** RAM\_IMAGE] are described in [Table : Arguments for advanced usage](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#nvm_advanced_usage__table_nvm_adv_usage).

### OTP fields

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

[Table : OTP fields](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#otp_fields__table_otp_fields) lists the details of the supported fields that are in the otp\_field\_list.yaml file.

Note: The permission fields are one-time programmable. Don't write them to 1 if you want to change the relative field values later.

Table : OTP fields

| Field | Max size (bits) | Read | Write |
| --- | --- | --- | --- |
| READ\_PERMISSION\_HW\_ENCRYPTION\_KEY | 1 | Yes | Yes |
| WRITE\_PERMISSION\_READ\_WRITE\_PERMISIONS | 1 | Yes | Yes |
| WRITE\_PERMISSION\_HW\_ENCRYPTION\_KEY | 1 | Yes | Yes |
| WRITE\_PERMISSION\_PK\_HASH | 1 | Yes | Yes |
| WRITE\_PERMISSION\_OEM\_SECURE\_BOOT | 1 | Yes | Yes |
| WRITE\_PERMISSION\_ANTI\_ROLL\_BACK | 1 | Yes | Yes |
| WRITE\_PERMISSION\_FIRMWARE | 1 | Yes | Yes |
| HW\_ENCRYPTION\_KEY | 128 | Yes | Yes |
| PK\_HASH | 256 | Yes | Yes |
| TOTAL\_ROT\_NUM | 4 | Yes | Yes |
| MODEL\_ID | 16 | Yes | Yes |
| SECURE\_BOOT\_ENFORCE | 3 | Yes | Yes |
| OEM\_ID | 16 | Yes | Yes |
| OEM\_DEBUG\_DISABLE | 8 | Yes | Yes |
| DISABLE\_QC\_RMA | 1 | Yes | Yes |
| HASH\_INTG\_CHK\_DISABLE | 1 | Yes | Yes |
| ROT\_INDEX | 8 | Yes | Yes |
| M4\_ANTI\_ROLLBACK | 64 | Yes | Yes |
| MAC\_ADDRESSES | 48 | Yes | Yes |
| MODULE\_PART\_NUMBER | 192 | Yes | Yes |
| MANUFACTURING\_Yr/Week | 16 | Yes | Yes |
| BOM\_CONFIGURATION | 16 | Yes | Yes |
| BDF\_CALIBRATION\_FLAG | 8 | Yes | Yes |

### Usage examples

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

### Read an OTP field

Use the `-g` parameter to read one OTP field value, as shown in the following example:

    python nvm_programmer.py -s ch347 -n otp -g OEM_ID
    Read OTP OEM_ID from command line.
    OEM_ID=0XABCDCopy to clipboard

### Write an OTP field

There are two methods for programing OTP fields:

- Using the parameter `-k` to directly specify one OTP field to be written, as shown in the following example:

        python nvm_programmer.py -s ch347 -n otp -k OEM_ID=0xabcd
        Write OTP from command line.
        OEM_ID=0XABCD
        Write OTP OEM_ID success.Copy to clipboard
- Using the `-config` parameter to specify a controlling YAML file as the source of OTP field data. This method can write an entire group of OTP values in a single
                        command, as shown in the following
                        example:

        python nvm_programmer.py -s ch347 --config config.yamlCopy to clipboard

    This example uses the config.yaml file in the qccsdk\tools\nvm\_programmer\script folder. The file contains the following data:

        OTP: 
        HW_ENCRYPTION_KEY: 0x0000ffff
        PK_HASH: 0x05b3b37f4165fe0c053a01c163555c54622aededfa9b73277c629afaee66e55d
            TOTAL_ROT_NUM: 0xF
            MODEL_ID: 0xabcd
            SECURE_BOOT_ENFORCE: 0x0
            OEM_ID: 0x1234
            OEM_DEBUG_DISABLE: 0x0
        DISABLE_QC_RMA: 0x1
            HASH_INTG_CHK_DISABLE: 0x0
            ROT_INDEX: 0x0F
            MAC_ADDRESSES: 0x446752016BB9Copy to clipboard

### Compare with an OTP field

Use the `--compare-key` parameter to compare one value with the current OTP field value, as shown in the following example:

python nvm_programmer.py -s ch347 -n otp --compare-key MAC_ADDRESSES=0x101010101010
    MAC_ADDRESSES in OTP=0x101010101010, the value is sameCopy to clipboard

### Key memory address

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

[Table : Key memory address used with the -b option](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html#key_memory_address_for_the_qcc730_nvm_programmer__table_key_mem_add) lists the important addresses when using the NVM	Programmer.

	

Table : Key memory address used with the -b option

| Address | Purpose |
| --- | --- |
| 0x200000 | Starting address of PBL						NVM region. |
| 0x208000 | Starting address of FDT. |
| 0x20a400 | Starting address of the SBLA region. |
| 0x212400 | Starting address of the SBLB region. |
| 0x21A400 | Starting address of Factory Mode or Mission Mode APPs image region. |
| 0x37A000 | Starting address of the BDF. |
| 0x043000 | Default starting address of QCLI\_DEMO when `--nvm-name` is set to `flash`, which means burn to external flash. |

### Executable location

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

Every board type needs its own programming image file named as FERMION\_NVM\_PROGRAMMER.elf file, so to provide RRAM/NOR-flash driver and UART driver, which use different GPIO
            configurations according to board type. The default output location when building the ELF image is: .\output\${boardName}\FERMION\_NVM\_PROGRAMMER\DEBUG\bin\.

	
For details of the build process, see [Getting started](https://docs.qualcomm.com/doc/80-Y8730-2/topic/qcc730_application_development.html).

	
The QCC730 SDK provides a default FERMION\_NVM\_PROGRAMMER.elf file in the .\tools\bin folder. You can also generate this image by
            running a build with `boardName` set to `mqm730x`.

### Create and use standalone NVM Programmer

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

By default, the NVM Programmer requires several tools installed on the computer, including GDB, OpenOCD, Python, and related libraries. This section describes how to package all the required components to create a standalone NVM programmer, which can run on a computer without the dependent tools installed.

Follow these steps to create a standalone NVM Programmer:

1. Download and install the following tools:
    - Python and related libraries
    - xPack GNU Arm embedded GCC
    - OpenOCD

    For details about how to download and install these tools, see the *Development environment setup* section in [QCC730 Evaluation Kit Quick Start Guide (80-Y8730-1)](doc/80-Y8730-1)

Note: To create a standalone NVM Programmer, installing xPack GNU Arm embedded GCC and OpenOCD is optional. You only need to copy the required components as described in the next step.
2. Copy the required components to a new folder as shown in the following table.

Note: As an example, the new folder is nvm in the **Destination** column.

| Required components | Destination | Size |
    | --- | --- | --- |
    | ***NVM Programmer*** | ***NVM Programmer*** | ***NVM Programmer*** |
    | qccsdk\tools\nvm\_programmer\scripts\nvm\_programmer.py | nvm\ | 236 KB |
    | The following folder and files under qccsdk\tools\fw\_upgrade\:<br><ul class="ul" id="create_and_use_standalone_nvm_programmer__ul_gvt_ysv_y2c"><br>                                        <li class="li">The <span class="ph filepath">__pycache__</span> folder</li><br><br>                                        <li class="li"><span class="ph filepath">download_config.xml</span></li><br><br>                                        <li class="li"><span class="ph filepath">fw_upgrade.xml</span></li><br><br>                                        <li class="li"><span class="ph filepath">gen*.py</span></li><br><br>                                    </ul> | nvm\fw\_upgrade\ | 92.2 KB |
    | The following folder and files under qccsdk\tools\nvm\_programmer\scripts\gdb\_framework\:<br><ul class="ul" id="create_and_use_standalone_nvm_programmer__ul_hvt_ysv_y2c"><br>                                        <li class="li">The <span class="ph filepath">__pycache__</span> folder</li><br><br>                                        <li class="li"><span class="ph filepath">gdb*.py</span></li><br><br>                                        <li class="li"><span class="ph filepath">hexfile.py</span></li><br><br>                                    </ul> | nvm\gdb\_framework\ | 56.5 KB |
    | ***OpenOCD*** | ***OpenOCD*** | ***OpenOCD*** |
    | The following files under {system install path}\OpenOCD\_CH347\bin\:<br><ul class="ul" id="create_and_use_standalone_nvm_programmer__ul_ivt_ysv_y2c"><br>                                        <li class="li"><span class="ph filepath">openocd.exe</span></li><br><br>                                        <li class="li"><span class="ph filepath">libhidapi-0.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libusb-1.0.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">qcc730_openocd_ch347.cfg</span></li><br><br>                                    </ul> | nvm\ | 5330 KB |
    | ***xPack GNU Arm embedded GCC*** | ***xPack GNU Arm embedded GCC*** | ***xPack GNU Arm embedded GCC*** |
    | The following files under {system install path}\xpack-arm-none-eabi-gcc-12.2.1-1.2\bin\:<br><ul class="ul" id="create_and_use_standalone_nvm_programmer__ul_jvt_ysv_y2c"><br>                                        <li class="li"><span class="ph filepath">arm-none-eabi-gdb-py3.exe</span></li><br><br>                                        <li class="li"><span class="ph filepath">libgcc_s_seh-1.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libgmp-10.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libiconv-2.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libmpc-3.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libmpfr-4.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libstdc++-6.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libwinpthread-1.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">libzstd.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">python311.dll</span></li><br><br>                                        <li class="li"><span class="ph filepath">python311.zipped</span></li><br><br>                                    </ul> | nvm\bin\ | 35.4 MB |
    | Everything under {system install path}\xpack-arm-none-eabi-gcc-12.2.1-1.2\bin\DLLs\ | nvm\bin\DLLs\ | 35.4 MB |
    | Everything under {system install path}\xpack-arm-none-eabi-gcc-12.2.1-1.2\arm-none-eabi\share\gdb\python\gdb\ | nvm\arm-none-eabi\share\gdb\python\gdb\ | 321 KB |
    |  |  |  |
3. Run the following command under the nvm folder to generate the standalone NVM Programmer:

        pyinstaller -F .\nvm_programmer.py --clean --add-data .\gdb_framework:gdb_framework --hidden-import=gdb_framework.gdb_server_ch347 --hidden-import=gdb_framework.gdb_server_jlink --add-data .\bin:bin --add-data .\arm-none-eabi:arm-none-eabi --add-data .\*:.Copy to clipboard

The standalone NVM Programmer (nvm\_programmer.exe) is generated in the nvm\dist\ folder.

### Use standalone NVM Programmer

The following commands show how to use the standalone NVM Programmer to flash images.

    set PACK_ENABLE=True
    nvm_programmer.exe -s ch347 --nvm-name rram -i FERMION_NVM_PROGRAMMER.elf -b 0x208000 -f {frn_curr_age_with_app_bin.bin} --reset
    nvm_programmer.exe -s ch347 --nvm-name rram -i FERMION_NVM_PROGRAMMER.elf -b 0x21a400 -f {FERMION_IOE_QCLI_DEMO.bin} --reset
    nvm_programmer.exe -s ch347 --nvm-name rram -i FERMION_NVM_PROGRAMMER.elf -b 0x20a400 -f {FERMION_SBL_HASHED.elf} --resetCopy to clipboard

Note: Always flash `frn_curr_age_with_app_bin.bin` before any other images.

### BDF calibration protection

Source: [https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html](https://docs.qualcomm.com/doc/80-Y8730-2/topic/sdk_tools_for_building_and_flashing_images.html)

The BDF calibration protection flag `BDF_CALIBRATION_FLAG` indicates the calibration state:

- 0: Not calibrated
- 1: Calibration completed

This flag works as follows:

1. When the flag is 0 (not calibrated), BDF flashing is allowed by default.
2. After calibration is performed using QDART, the BDF binary is updated and the flag is automatically set to 1.
3. When the flag is 1 (calibrated), flashing the BDF requires the explicit `--force` option.
4. Any manual BDF flashing (for example, forced flashing or non-QDART calibration) clears the flag (sets it to 0), because the data is no longer factory calibrated.

**Commands:**

- Check the BDF calibration protection flag:

        python nvm_programmer.py -s ch347 -n otp -g BDF_CALIBRATION_FLAGCopy to clipboard
- Force flash a BDF binary:

        python nvm_programmer.py -s ch347 --nvm-name rram -b 0x37A000 -f {your_BDF_bin} --force --resetCopy to clipboard
- Export the BDF binary:

    If you want to back up or inspect the BDF binary, use the `--export-bdf` option.

        python nvm_programmer.py -s ch347 --export-bdf backup.binCopy to clipboard

Last Published: Jun 03, 2026

[Previous Topic
QCC730 OTA upgrade](https://docs.qualcomm.com/bundle/publicresource/80-Y8730-2/topics/firmware_upgrade.md) [Next Topic
Communication interfaces](https://docs.qualcomm.com/bundle/publicresource/80-Y8730-2/topics/communication_interfaces.md)