Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Add Zigbee DFU image support #161

Merged
merged 7 commits into from Sep 21, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 23 additions & 4 deletions README.md
Expand Up @@ -14,6 +14,7 @@ This application and its library offer the following features:
* Bootloader DFU settings generation and display
* Device Firmware Update procedure over Bluetooth Low Energy
* Device Firmware Update procedure over Thread
* Device Firmware Update procedure over Zigbee

## License

Expand Down Expand Up @@ -44,7 +45,7 @@ This will also retrieve and install all additional required packages.

**Note**: When installing on macOS, you may need to add ` --ignore-installed six` when running pip. See [issue #79](https://github.com/NordicSemiconductor/pc-nrfutil/issues/79).

**Note**: To use the `dfu ble` or `dfu thread` option you will need to set up your boards to be able to communicate with your computer. You can find additional information here: [Hardware setup](https://github.com/NordicSemiconductor/pc-ble-driver/blob/master/Installation.md#hardware-setup).
**Note**: To use the `dfu ble`, `dfu thread`, or `dfu zigbee` option you will need to set up your boards to be able to communicate with your computer. You can find additional information here: [Hardware setup](https://github.com/NordicSemiconductor/pc-ble-driver/blob/master/Installation.md#hardware-setup).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: I believe the last comma should be left out: /dfu thread, or dfu zigbee/dfu thread or dfu zigbee/
Same on line 106.


## Downloading precompiled Windows executable

Expand Down Expand Up @@ -102,7 +103,7 @@ pyinstaller /full/path/to/nrfutil.spec

**Note**: Please refer to the [pc-ble-driver-py PyPI installation note on Windows](https://github.com/NordicSemiconductor/pc-ble-driver-py#installing-from-pypi) if you are running nrfutil on this operating system.

**Note**: To use the `dfu ble` or `dfu thread` option you will need to set up your boards to be able to communicate with your computer. You can find additional information here: [Hardware setup](https://github.com/NordicSemiconductor/pc-ble-driver/blob/master/Installation.md#hardware-setup).
**Note**: To use the `dfu ble`, `dfu thread`, or `dfu zigbee` option you will need to set up your boards to be able to communicate with your computer. You can find additional information here: [Hardware setup](https://github.com/NordicSemiconductor/pc-ble-driver/blob/master/Installation.md#hardware-setup).

## Usage

Expand Down Expand Up @@ -157,7 +158,7 @@ SoftDevice | FWID (sd-req)
`s140_nrf52_6.0.0` | 0xA9
`s140_nrf52_6.1.0` | 0xAE

**Note**: The Thread stack doesn't use a SoftDevice but --sd-req option is required for compatibility reasons. You can provide any value for the option as it is ignored during DFU.
**Note**: The Thread, and Zigbee stacks don't use a SoftDevice but --sd-req option is required for compatibility reasons. You can provide any value for the option as it is ignored during DFU.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comma: /The Thread, and Zigbee stacks/The Thread and Zigbee stacks/


Not all combinations of Bootloader, SoftDevice and Application are possible when generating a package. The table below summarizes the support for different combinations.

Expand All @@ -183,6 +184,12 @@ SD + APP | Yes | **See notes 1 and 2 below**
was added in nrfutil 3.1.0 and is required since 3.2.0 in case the package should contain SD (+ BL) + APP. Also, since version 3.2.0 the new ID is copied to `--sd-req` list so that
in case of a link loss during APP update the DFU process can be restarted. In that case the new SD would overwrite itself, so `--sd-req` must contain also the ID of the new SD.

The boolean option '--zigbee' enables the generation of Zigbee update file in addition to the zip package. The following example demostrates the generation of such update file:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: /demostrates/demonstrates/

```
nrfutil pkg generate --hw-version 52 --sd-req 0 --application-version 0x01020101 --application nrf52840_xxaa.hex --key-file ../priv.pem app_dfu_package.zip --zigbee True --manufacturer-id 0xCAFE --image-type 0x1234 --comment good_image
```
**Note 3:** The generated Zigbee update file is named according to the recomendation of the Zigbee Specification ([Zigbee Cluster Library Specification 11.5 - Zigbee Document 07-5123-06](http://www.zigbee.org/~zigbeeor/wp-content/uploads/2014/10/07-5123-06-zigbee-cluster-library-specification.pdf)), so the user doesn't provide the name of the Update file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: /recomendation/recommendation/


##### display
Use this option to display the contents of a DFU package in a .zip file.
```
Expand Down Expand Up @@ -218,7 +225,19 @@ nrfutil dfu ble -pkg app_dfu_package.zip -p COM3 -f
```
The `-f` option instructs nrfutil to actually program the board connected to COM3 with the connectivity software required to operate as a network co-processor (NCP). Use with caution as this will overwrite the contents of the IC's flash memory.

##### serial
##### Zigbee
**Note**: DFU over Zigbee OTA is experimental

Perform a full DFU procedure over Zigbee network using ZCL OTA Upgrade Cluster. This command takes several options that you can list using:
```
nrfutil dfu zigbee --help
```
Below is an example of the execution of a DFU procedure using a file generated above using a OTA Upgrade server deployed on a DK with a OTA Upgrade Server operating on the 802.15.4 channel.
```
nrfutil dfu zigbee -f CAFE-1234-good_image.zigbee -snr 683604699 -chan 20
```

##### Serial

Perform a full DFU procedure over a UART serial line. The DFU target shall be configured to use some of its digital I/O pins as UART.

Expand Down
100 changes: 98 additions & 2 deletions nordicsemi/__main__.py
Expand Up @@ -457,6 +457,22 @@ def pkg():
help='The private (signing) key in PEM fomat.',
required=False,
type=click.Path(exists=True, resolve_path=True, file_okay=True, dir_okay=False))
@click.option('--zigbee',
help='Create an image and distribution package for Zigbee DFU server.',
required=False,
type=click.BOOL)
@click.option('--zigbee-manufacturer-id',
help='Manufacturer ID to be used in Zigbee OTA header.',
required=False,
type=BASED_INT)
@click.option('--zigbee-image-type',
help='Image type to be used in Zigbee OTA header.',
required=False,
type=BASED_INT)
@click.option('--zigbee-comment',
help='Firmware comment to be used in Zigbee OTA header.',
required=False,
type=click.STRING)
def generate(zipfile,
debug_mode,
application,
Expand All @@ -468,7 +484,11 @@ def generate(zipfile,
sd_req,
sd_id,
softdevice,
key_file):
key_file,
zigbee,
zigbee_manufacturer_id,
zigbee_image_type,
zigbee_comment):
"""
Generate a zip package for distribution to apps that support Nordic DFU OTA.
The application, bootloader, and SoftDevice files are converted to .bin if supplied as .hex files.
Expand Down Expand Up @@ -621,6 +641,21 @@ def generate(zipfile,
if default_key:
display_sec_warning()

if zigbee_comment is None:
zigbee_comment = ''
elif any(ord(char) > 127 for char in zigbee_comment): # Check if all the characters belong to the ASCII range
click.echo('Warning: Non-ASCII characters in the comment are not allowed. Discarding comment.')
zigbee_comment = ''
elif len(zigbee_comment) > 30:
click.echo('Warning: truncating the comment to 30 bytes.')
zigbee_comment = zigbee_comment[:30]

if zigbee_manufacturer_id is None:
zigbee_manufacturer_id = 0xFFFF

if zigbee_image_type is None:
zigbee_image_type = 0xFFFF

package = Package(debug_mode,
hw_version,
application_version_internal,
Expand All @@ -630,10 +665,38 @@ def generate(zipfile,
application,
bootloader,
softdevice,
key_file)
key_file,
zigbee,
zigbee_manufacturer_id,
zigbee_image_type,
zigbee_comment)

package.generate_package(zipfile_path)

# Regenerate BLE DFU package for Zigbee DFU purposes.
if zigbee:
from shutil import copyfile
from os import remove

log_message = "Zigbee update created at {0}".format(package.zigbee_ota_file.filename)
click.echo(log_message)

binfile = package.zigbee_ota_file.filename.replace(".zigbee", ".bin")
copyfile(package.zigbee_ota_file.filename, binfile)
package = Package(debug_mode,
hw_version,
application_version_internal,
bootloader_version,
sd_req_list,
sd_id_list,
binfile,
bootloader,
softdevice,
key_file)

package.generate_package(zipfile_path)
remove(binfile)

log_message = "Zip created at {0}".format(zipfile_path)
click.echo(log_message)

Expand Down Expand Up @@ -986,5 +1049,38 @@ def thread(package, port, address, server_port, panid, channel, jlink_snr, flash
finally:
transport.close()

@dfu.command(short_help="Update the firmware on a device over a Zigbee connection.")
@click.option('-f', '--file',
help='Filename of the Zigbee OTA Upgrade file.',
type=click.Path(exists=True, resolve_path=True, file_okay=True, dir_okay=False),
required=True)
@click.option('-snr', '--jlink_snr',
help='JLink serial number of the devboard which shall serve as a OTA Server cluster',
type=click.STRING)
@click.option('-chan', '--channel',
help='802.15.4 Channel that the OTA server will use',
type=click.INT)

def zigbee(file, jlink_snr, channel):
"""
Perform a Device Firmware Update on a device that implements a Zigbee OTA Client cluster.
This requires a second nRF device, connected to this computer, which shall serve as a
OTA Server cluster.
"""
ble_driver_init('NRF52')
from nordicsemi.zigbee.ota_flasher import OTAFlasher
of = OTAFlasher(fw = file, channel = channel, snr = jlink_snr)

if of.fw_check():
click.echo("Board already flashed with connectivity firmware.")
else:
click.echo("Flashing connectivity firmware...")
of.fw_flash()
click.echo("Connectivity firmware flashed.")

of.reset()
time.sleep(3.0) # A delay to init the OTA Server flashed on the devboard and the CLI inside of it
of.setup_channel()

if __name__ == '__main__':
cli()
34 changes: 33 additions & 1 deletion nordicsemi/dfu/package.py
Expand Up @@ -55,6 +55,7 @@
from nordicsemi.dfu.manifest import ManifestGenerator, Manifest
from nordicsemi.dfu.model import HexType, FirmwareKeys
from nordicsemi.dfu.crc16 import *
from nordicsemi.zigbee.ota_file import *

from .signing import Signing

Expand Down Expand Up @@ -121,7 +122,11 @@ def __init__(self,
app_fw=None,
bootloader_fw=None,
softdevice_fw=None,
key_file=None):
key_file=None,
zigbee_format=False,
manufacturer_id=0,
image_type=0,
comment=''):
"""
Constructor that requires values used for generating a Nordic DFU package.

Expand Down Expand Up @@ -176,6 +181,17 @@ def __init__(self,
self.work_dir = None
self.manifest = None

if zigbee_format:
self.is_zigbee = True
self.image_type = image_type
self.manufacturer_id = manufacturer_id
self.comment = comment
else:
self.is_zigbee = False
self.image_type = None
self.manufacturer_id = None
self.comment = None

def __del__(self):
"""
Destructor removes the temporary working directory
Expand Down Expand Up @@ -393,6 +409,22 @@ def generate_package(self, filename, preserve_work_dir=False):
firmware_data[FirmwareKeys.DAT_FILENAME] = \
init_packet_filename

if self.is_zigbee:
self.zigbee_ota_file = OTA_file(firmware_data[FirmwareKeys.INIT_PACKET_DATA][PacketField.FW_VERSION],
len(init_packet.get_init_packet_pb_bytes()),
binascii.crc32(init_packet.get_init_packet_pb_bytes()) & 0xFFFFFFFF,
init_packet.get_init_packet_pb_bytes(),
os.path.getsize(firmware_data[FirmwareKeys.BIN_FILENAME]),
self.calculate_crc(32, firmware_data[FirmwareKeys.BIN_FILENAME]) & 0xFFFFFFFF,
bytes(open(firmware_data[FirmwareKeys.BIN_FILENAME]).read()),
self.manufacturer_id,
self.image_type,
self.comment)

ota_file_handle = open(self.zigbee_ota_file.filename, 'wb')
ota_file_handle.write(self.zigbee_ota_file.binary)
ota_file_handle.close()

# Store the manifest to manifest.json
manifest = self.create_manifest()

Expand Down
2 changes: 1 addition & 1 deletion nordicsemi/version.py
Expand Up @@ -37,4 +37,4 @@

""" Version definition for nrfutil. """

NRFUTIL_VERSION = "3.5.1"
NRFUTIL_VERSION = "3.6.0"
38 changes: 38 additions & 0 deletions nordicsemi/zigbee/__init__.py
@@ -0,0 +1,38 @@
#
# Copyright (c) 2018 Nordic Semiconductor ASA
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# 3. Neither the name of Nordic Semiconductor ASA nor the names of other
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# 4. This software must only be used in or with a processor manufactured by Nordic
# Semiconductor ASA, or in or with a processor manufactured by a third party that
# is used in combination with a processor manufactured by Nordic Semiconductor.
#
# 5. Any software provided in binary or object form under this license must not be
# reverse engineered, decompiled, modified and/or disassembled.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

"""Package with Zigbee OTA file functionality."""