|  | #!/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)) |