#!/usr/bin/env python3 # Copyright (c) 2020-2021 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Flash an NRF5 device. This is layered so that a caller can perform individual operations through an `Flasher` instance, or operations according to a command line. For `Flasher`, see the class documentation. For the parse_command() interface or standalone execution: usage: nrfconnect_firmware_utils.py [-h] [--verbose] [--erase] [--application FILE] [--verify_application] [--reset] [--skip_reset] [--nrfjprog FILE] [--snr SERIAL] [--family FAMILY] Flash NRF5 device optional arguments: -h, --help show this help message and exit configuration: --verbose, -v Report more verbosely --nrfjprog FILE File name of the nrfjprog executable --snr SERIAL, --serial SERIAL, -s SERIAL Serial number of device to flash --family FAMILY NRF5 device family operations: --erase Erase device --application FILE Flash an image --verify_application, --verify-application Verify the image after flashing --reset Reset device after flashing --skip_reset, --skip-reset Do not reset device after flashing """ import os import sys import firmware_utils # Additional options that can be use to configure an `Flasher` # object (as dictionary keys) and/or passed as command line options. NRF5_OPTIONS = { # Configuration options define properties used in flashing operations. 'configuration': { # Tool configuration options. 'nrfjprog': { 'help': 'File name of the nrfjprog executable', 'default': 'nrfjprog', 'argparse': { 'metavar': 'FILE' }, 'command': [ '{nrfjprog}', {'optional': 'family'}, {'optional': 'snr'}, () ], 'verify': ['{nrfjprog}', '--version'], 'error': """\ Unable to execute {nrfjprog}. Please ensure that this tool is installed and available. See the NRF5 example README for installation instructions. """, }, 'snr': { 'help': 'Serial number of device to flash', 'default': None, 'alias': ['--serial', '-s'], 'argparse': { 'metavar': 'SERIAL' }, }, # Device configuration options. 'family': { 'help': 'NRF5 device family', 'default': None, 'argparse': { 'metavar': 'FAMILY' }, }, }, } class Flasher(firmware_utils.Flasher): """Manage nrf5 flashing.""" def __init__(self, **options): super().__init__(platform='NRF5', module=__name__, **options) self.define_options(NRF5_OPTIONS) def erase(self): """Perform nrfjprog --eraseall""" return self.run_tool('nrfjprog', ['--eraseall'], name='Erase all') def verify(self, image): """Verify image.""" return self.run_tool('nrfjprog', ['--quiet', '--verify', image], name='Verify', pass_message='Verified', fail_message='Not verified', fail_level=2) def flash(self, image): """Flash image.""" return self.run_tool('nrfjprog', ['--program', image, '--sectoranduicrerase'], name='Flash') def reset(self): """Reset the device.""" return self.run_tool('nrfjprog', ['--reset'], name='Reset') def actions(self): """Perform actions on the device according to self.option.""" self.log(3, 'Options:', self.option) if self.option.erase: if self.erase().err: return self if self.option.application: application = self.option.application if self.flash(application).err: return self if self.option.verify_application: if self.verify(application).err: return self if self.option.reset is None: self.option.reset = True if self.option.reset: if self.reset().err: return self return self # Mobly integration class Nrf5Platform: def __init__(self, flasher_args): self.flasher = Flasher(**flasher_args) def flash(self): self.flasher.flash_command([os.getcwd()]) def verify_platform_args(platform_args): required_args = ['application'] for r in required_args: if r not in platform_args: raise ValueError("Required argument %s missing" % r) def create_platform(platform_args): verify_platform_args(platform_args[0]) return Nrf5Platform(platform_args[0]) # End of Mobly integration if __name__ == '__main__': sys.exit(Flasher().flash_command(sys.argv))