aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/nrfutil/nordicsemi/__main__.py
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
commit4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch)
tree65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/lib/nrfutil/nordicsemi/__main__.py
parent0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff)
add circuitpython code
Diffstat (limited to 'circuitpython/lib/nrfutil/nordicsemi/__main__.py')
-rw-r--r--circuitpython/lib/nrfutil/nordicsemi/__main__.py307
1 files changed, 307 insertions, 0 deletions
diff --git a/circuitpython/lib/nrfutil/nordicsemi/__main__.py b/circuitpython/lib/nrfutil/nordicsemi/__main__.py
new file mode 100644
index 0000000..02bb049
--- /dev/null
+++ b/circuitpython/lib/nrfutil/nordicsemi/__main__.py
@@ -0,0 +1,307 @@
+# Copyright (c) 2015, Nordic Semiconductor
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# * 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.
+#
+# * Neither the name of Nordic Semiconductor ASA nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# 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.
+
+"""nrfutil command line tool."""
+import logging
+import os
+import click
+
+from nordicsemi.dfu.dfu import Dfu
+from nordicsemi.dfu.dfu_transport import DfuEvent
+from nordicsemi.dfu.dfu_transport_serial import DfuTransportSerial
+from nordicsemi.dfu.package import Package
+from nordicsemi import version as nrfutil_version
+from nordicsemi.dfu.signing import Signing
+from nordicsemi.dfu.util import query_func
+
+
+class nRFException(Exception):
+ pass
+
+
+def int_as_text_to_int(value):
+ try:
+ if value[:2].lower() == '0x':
+ return int(value[2:], 16)
+ elif value[:1] == '0':
+ return int(value, 8)
+ return int(value, 10)
+ except ValueError:
+ raise nRFException('%s is not a valid integer' % value)
+
+
+class BasedIntOrNoneParamType(click.ParamType):
+ name = 'Int or None'
+
+ def convert(self, value, param, ctx):
+ try:
+ if value.lower() == 'none':
+ return 'none'
+ return int_as_text_to_int(value)
+ except nRFException:
+ self.fail('%s is not a valid integer' % value, param, ctx)
+
+BASED_INT_OR_NONE = BasedIntOrNoneParamType()
+
+
+class TextOrNoneParamType(click.ParamType):
+ name = 'Text or None'
+
+ def convert(self, value, param, ctx):
+ return value
+
+TEXT_OR_NONE = TextOrNoneParamType()
+
+
+@click.group()
+@click.option('--verbose',
+ help='Show verbose information',
+ is_flag=True)
+def cli(verbose):
+ if verbose:
+ logging.basicConfig(format='%(message)s', level=logging.INFO)
+ else:
+ logging.basicConfig(format='%(message)s')
+
+
+@cli.command()
+def version():
+ """Displays nrf utility version."""
+ click.echo("nrfutil version {}".format(nrfutil_version.NRFUTIL_VERSION))
+
+
+@cli.command(short_help='Generate keys for signing or generate public keys')
+@click.argument('key_file', required=True)
+@click.option('--gen-key',
+ help='generate signing key and store at given path (pem-file)',
+ type=click.BOOL,
+ is_flag=True)
+@click.option('--show-vk',
+ help='Show the verification keys for DFU Signing (hex|code|pem)',
+ type=click.STRING)
+def keys(key_file,
+ gen_key,
+ show_vk):
+ """
+ This set of commands support creation of signing key (private) and showing the verification key (public)
+ from a previously loaded signing key. Signing key is stored in PEM format
+ """
+ if not gen_key and show_vk is None:
+ raise nRFException("Use either gen-key or show-vk.")
+
+ signer = Signing()
+
+ if gen_key:
+ if os.path.exists(key_file):
+ if not query_func("File found at %s. Do you want to overwrite the file?" % key_file):
+ click.echo('Key generation aborted')
+ return
+
+ signer.gen_key(key_file)
+ click.echo("Generated key at: %s" % key_file)
+
+ elif show_vk:
+ if not os.path.isfile(key_file):
+ raise nRFException("No key file to load at: %s" % key_file)
+
+ signer.load_key(key_file)
+ click.echo(signer.get_vk(show_vk))
+
+
+@cli.group()
+def dfu():
+ """
+ This set of commands support Nordic DFU OTA package generation for distribution to
+ applications and serial DFU.
+ """
+ pass
+
+
+@dfu.command(short_help='Generate a package for distribution to Apps supporting Nordic DFU OTA')
+@click.argument('zipfile',
+ required=True,
+ type=click.Path())
+@click.option('--application',
+ help='The application firmware file',
+ type=click.STRING)
+@click.option('--application-version',
+ help='Application version, default: 0xFFFFFFFF',
+ type=BASED_INT_OR_NONE,
+ default=str(Package.DEFAULT_APP_VERSION))
+@click.option('--bootloader',
+ help='The bootloader firmware file',
+ type=click.STRING)
+@click.option('--dev-revision',
+ help='Device revision, default: 0xFFFF',
+ type=BASED_INT_OR_NONE,
+ default=str(Package.DEFAULT_DEV_REV))
+@click.option('--dev-type',
+ help='Device type, default: 0xFFFF',
+ type=BASED_INT_OR_NONE,
+ default=str(Package.DEFAULT_DEV_TYPE))
+@click.option('--dfu-ver',
+ help='DFU packet version to use, default: 0.5',
+ type=click.FLOAT,
+ default=Package.DEFAULT_DFU_VER)
+@click.option('--sd-req',
+ help='SoftDevice requirement. A list of SoftDevice versions (1 or more)'
+ 'of which one is required to be present on the target device.'
+ 'Example: --sd-req 0x4F,0x5A. Default: 0xFFFE.',
+ type=TEXT_OR_NONE,
+ default=str(Package.DEFAULT_SD_REQ[0]))
+@click.option('--softdevice',
+ help='The SoftDevice firmware file',
+ type=click.STRING)
+@click.option('--key-file',
+ help='Signing key (pem fomat)',
+ type=click.Path(exists=True, resolve_path=True, file_okay=True, dir_okay=False))
+def genpkg(zipfile,
+ application,
+ application_version,
+ bootloader,
+ dev_revision,
+ dev_type,
+ dfu_ver,
+ sd_req,
+ softdevice,
+ key_file):
+ """
+ Generate a zipfile package for distribution to Apps supporting Nordic DFU OTA.
+ The application, bootloader and softdevice files are converted to .bin if it is a .hex file.
+ For more information on the generated init packet see:
+ http://developer.nordicsemi.com/nRF51_SDK/doc/7.2.0/s110/html/a00065.html
+ """
+ zipfile_path = zipfile
+
+ if application_version == 'none':
+ application_version = None
+
+ if dev_revision == 'none':
+ dev_revision = None
+
+ if dev_type == 'none':
+ dev_type = None
+
+ sd_req_list = None
+
+ if sd_req.lower() == 'none':
+ sd_req_list = []
+ elif sd_req:
+ try:
+ # This will parse any string starting with 0x as base 16.
+ sd_req_list = sd_req.split(',')
+ sd_req_list = map(int_as_text_to_int, sd_req_list)
+ except ValueError:
+ raise nRFException("Could not parse value for --sd-req. "
+ "Hex values should be prefixed with 0x.")
+
+ if key_file and dfu_ver < 0.8:
+ click.echo("Key file was given, setting DFU version to 0.8")
+
+ package = Package(dev_type,
+ dev_revision,
+ application_version,
+ sd_req_list,
+ application,
+ bootloader,
+ softdevice,
+ dfu_ver,
+ key_file)
+
+ package.generate_package(zipfile_path)
+
+ log_message = "Zip created at {0}".format(zipfile_path)
+ click.echo(log_message)
+
+
+global_bar = None
+
+
+def update_progress(progress=0, done=False, log_message=""):
+ del done, log_message # Unused parameters
+ #global global_bar
+ #if global_bar is None:
+ # with click.progressbar(length=100) as bar:
+ # global_bar = bar
+ #global_bar.update(max(1, progress))
+ click.echo('#', nl=False)
+
+
+@dfu.command(short_help="Program a device with bootloader that support serial DFU")
+@click.option('-pkg', '--package',
+ help='DFU package filename',
+ type=click.Path(exists=True, resolve_path=True, file_okay=True, dir_okay=False),
+ required=True)
+@click.option('-p', '--port',
+ help='Serial port COM Port to which the device is connected',
+ type=click.STRING,
+ required=True)
+@click.option('-b', '--baudrate',
+ help='Desired baud rate 38400/96000/115200/230400/250000/460800/921600/1000000 (default: 38400). '
+ 'Note: Physical serial ports (e.g. COM1) typically do not support baud rates > 115200',
+ type=click.INT,
+ default=DfuTransportSerial.DEFAULT_BAUD_RATE)
+@click.option('-fc', '--flowcontrol',
+ help='Enable flow control, default: disabled',
+ type=click.BOOL,
+ is_flag=True)
+@click.option('-sb', '--singlebank',
+ help='Single band bootloader to skip firmware activating delay, default: Dual bank',
+ type=click.BOOL,
+ is_flag=True)
+def serial(package, port, baudrate, flowcontrol, singlebank):
+ """Program a device with bootloader that support serial DFU"""
+ serial_backend = DfuTransportSerial(port, baudrate, flowcontrol, singlebank)
+ serial_backend.register_events_callback(DfuEvent.PROGRESS_EVENT, update_progress)
+ dfu = Dfu(package, dfu_transport=serial_backend)
+
+ click.echo("Upgrading target on {1} with DFU package {0}. Flow control is {2}, {3} bank mode"
+ .format(package, port, "enabled" if flowcontrol else "disabled", "Single" if singlebank else "Dual"))
+
+ try:
+ dfu.dfu_send_images()
+
+ except Exception as e:
+ click.echo("")
+ click.echo("Failed to upgrade target. Error is: {0}".format(e.message))
+ click.echo("")
+ click.echo("Possible causes:")
+ click.echo("- Selected Bootloader version does not match the one on Bluefruit device.")
+ click.echo(" Please upgrade the Bootloader or select correct version in Tools->Bootloader.")
+ click.echo("- Baud rate must be 115200, Flow control must be off.")
+ click.echo("- Target is not in DFU mode. Ground DFU pin and RESET and release both to enter DFU mode.")
+
+ return False
+
+ click.echo("Device programmed.")
+
+ return True
+
+
+if __name__ == '__main__':
+ cli()