nrfconnect_firmware_utils.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2020-2021 Project CHIP Authors
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Flash an NRF5 device.
  16. This is layered so that a caller can perform individual operations
  17. through an `Flasher` instance, or operations according to a command line.
  18. For `Flasher`, see the class documentation. For the parse_command()
  19. interface or standalone execution:
  20. usage: nrfconnect_firmware_utils.py [-h] [--verbose] [--erase]
  21. [--application FILE]
  22. [--verify_application] [--reset]
  23. [--skip_reset] [--nrfjprog FILE]
  24. [--snr SERIAL] [--family FAMILY]
  25. Flash NRF5 device
  26. optional arguments:
  27. -h, --help show this help message and exit
  28. configuration:
  29. --verbose, -v Report more verbosely
  30. --nrfjprog FILE File name of the nrfjprog executable
  31. --snr SERIAL, --serial SERIAL, -s SERIAL
  32. Serial number of device to flash
  33. --family FAMILY NRF5 device family
  34. operations:
  35. --erase Erase device
  36. --application FILE Flash an image
  37. --verify_application, --verify-application
  38. Verify the image after flashing
  39. --reset Reset device after flashing
  40. --skip_reset, --skip-reset
  41. Do not reset device after flashing
  42. """
  43. import os
  44. import sys
  45. import firmware_utils
  46. # Additional options that can be use to configure an `Flasher`
  47. # object (as dictionary keys) and/or passed as command line options.
  48. NRF5_OPTIONS = {
  49. # Configuration options define properties used in flashing operations.
  50. 'configuration': {
  51. # Tool configuration options.
  52. 'nrfjprog': {
  53. 'help': 'File name of the nrfjprog executable',
  54. 'default': 'nrfjprog',
  55. 'argparse': {
  56. 'metavar': 'FILE'
  57. },
  58. 'command': [
  59. '{nrfjprog}',
  60. {'optional': 'family'},
  61. {'optional': 'snr'},
  62. ()
  63. ],
  64. 'verify': ['{nrfjprog}', '--version'],
  65. 'error':
  66. """\
  67. Unable to execute {nrfjprog}.
  68. Please ensure that this tool is installed and
  69. available. See the NRF5 example README for
  70. installation instructions.
  71. """,
  72. },
  73. 'snr': {
  74. 'help': 'Serial number of device to flash',
  75. 'default': None,
  76. 'alias': ['--serial', '-s'],
  77. 'argparse': {
  78. 'metavar': 'SERIAL'
  79. },
  80. },
  81. # Device configuration options.
  82. 'family': {
  83. 'help': 'NRF5 device family',
  84. 'default': None,
  85. 'argparse': {
  86. 'metavar': 'FAMILY'
  87. },
  88. },
  89. },
  90. }
  91. class Flasher(firmware_utils.Flasher):
  92. """Manage nrf5 flashing."""
  93. def __init__(self, **options):
  94. super().__init__(platform='NRF5', module=__name__, **options)
  95. self.define_options(NRF5_OPTIONS)
  96. def erase(self):
  97. """Perform nrfjprog --eraseall"""
  98. return self.run_tool('nrfjprog', ['--eraseall'], name='Erase all')
  99. def verify(self, image):
  100. """Verify image."""
  101. return self.run_tool('nrfjprog',
  102. ['--quiet', '--verify', image],
  103. name='Verify',
  104. pass_message='Verified',
  105. fail_message='Not verified',
  106. fail_level=2)
  107. def flash(self, image):
  108. """Flash image."""
  109. return self.run_tool('nrfjprog',
  110. ['--program', image, '--sectoranduicrerase'],
  111. name='Flash')
  112. def reset(self):
  113. """Reset the device."""
  114. return self.run_tool('nrfjprog', ['--reset'], name='Reset')
  115. def actions(self):
  116. """Perform actions on the device according to self.option."""
  117. self.log(3, 'Options:', self.option)
  118. if self.option.erase:
  119. if self.erase().err:
  120. return self
  121. if self.option.application:
  122. application = self.option.application
  123. if self.flash(application).err:
  124. return self
  125. if self.option.verify_application:
  126. if self.verify(application).err:
  127. return self
  128. if self.option.reset is None:
  129. self.option.reset = True
  130. if self.option.reset:
  131. if self.reset().err:
  132. return self
  133. return self
  134. # Mobly integration
  135. class Nrf5Platform:
  136. def __init__(self, flasher_args):
  137. self.flasher = Flasher(**flasher_args)
  138. def flash(self):
  139. self.flasher.flash_command([os.getcwd()])
  140. def verify_platform_args(platform_args):
  141. required_args = ['application']
  142. for r in required_args:
  143. if r not in platform_args:
  144. raise ValueError("Required argument %s missing" % r)
  145. def create_platform(platform_args):
  146. verify_platform_args(platform_args[0])
  147. return Nrf5Platform(platform_args[0])
  148. # End of Mobly integration
  149. if __name__ == '__main__':
  150. sys.exit(Flasher().flash_command(sys.argv))