Source code for nanaimo.instruments.jlink

#
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# This software is distributed under the terms of the MIT License.
#
#                                       (@@@@%%%%%%%%%&@@&.
#                              /%&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&@@(
#                              *@&%%%%%%%%%&&%%%%%%%%%%%%%%%%%%&&&%%%%%%%
#                               @   @@@(@@@@%%%%%%%%%%%%%%%%&@@&* @@@   .
#                               ,   .        .  .@@@&                   /
#                                .       .                              *
#                               @@              .                       @
#                              @&&&&&&@. .    .                     *@%&@
#                              &&&&&&&&&&&&&&&&@@        *@@############@
#                     *&/ @@ #&&&&&&&&&&&&&&&&&&&&@  ###################*
#                              @&&&&&&&&&&&&&&&&&&##################@
#                                 %@&&&&&&&&&&&&&&################@
#                                        @&&&&&&&&&&%#######&@%
#  nanaimo                                   (@&&&&####@@*
#
import tempfile
import textwrap
import typing

import nanaimo
import nanaimo.fixtures
import functools


[docs]class ProgramUploader(nanaimo.fixtures.SubprocessFixture): """ JLinkExe fixture that loads a given hexfile to a target device. """ fixture_name = 'nanaimo_jlink_upload' argument_prefix = 'jlink_up' script_template = textwrap.dedent(''' f device {device} speed {speed} si {serial_interface} connect hwinfo st h moe rx {reset_delay_millis} loadfile {hexfile} r qc ''').lstrip()
[docs] @classmethod def on_visit_test_arguments(cls, arguments: nanaimo.Arguments) -> None: super().on_visit_test_arguments(arguments) arguments.add_argument('--exe', default='JLinkExe', help='A path to the jlink commander executable.') arguments.add_argument('--hexfile', help='Path to a hex file to upload.') arguments.add_argument('--device', help='The target device.') arguments.add_argument('--interface-speed-khz', help='The interface speed in kilohertz', default='default') arguments.add_argument('--serial-interface', help='The serial interface to use (e.g. swd, jtag)', default='swd') arguments.add_argument('--reset-delay-millis', default=400, help='Milliseconds to wait after reset before starting to load the new image.') arguments.add_argument('--script', default=None, help=textwrap.dedent(''' Path to a jlink script to use. If not provided then an script will be generated using an internal default. The following template parameters are supported but optional: {device} = The target device. {speed} = The interface speed in kilohertz {serial_interface} = The serial interface to use. {reset_delay_millis} = An optional delay to include after reset. {hexfile} = The hexfile to upload. ''').lstrip())
[docs] def on_construct_command(self, arguments: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) -> str: """ Construct a command to upload (aka "flash") a firmware to a target device using Segger's JLink Commander program with the assumption that a Segger debug probe like the JLink is attached to the system. +----------------+---------------------------------------+--------------------------------------------------+ | **Artifacts** | | | +----------------+---------------------------------------+--------------------------------------------------+ | key | type | Notes | +================+=======================================+==================================================+ | ``tmpfile`` | Optional[tempfile.NamedTemporaryFile] | A temporary file containing the jlink script to | | | | execute with expanded template parameters. | +----------------+---------------------------------------+--------------------------------------------------+ | ``scriptfile`` | Optional[str] | A path to a script file used to invoke jlink. | | | | This file can contain template parameters. | +----------------+---------------------------------------+--------------------------------------------------+ """ script_file_path = self.get_arg_covariant(arguments, 'script') tmpfile = tempfile.NamedTemporaryFile(mode='w') setattr(inout_artifacts, 'tmpfile', tmpfile) # without a script, other args are required: get_arg_func = functools.partial(self.get_arg_covariant_or_fail, arguments) if script_file_path is None: # keep around for as long as the command exists. setattr(inout_artifacts, 'scriptfile', None) template = self.script_template else: setattr(inout_artifacts, 'scriptfile', script_file_path) with open(script_file_path, 'r') as user_script_file: template = user_script_file.read() get_arg_func = functools.partial(self.get_arg_covariant, arguments) # don't fail fixture on missing args # poor man's templating expanded_script_file = template.format( hexfile=get_arg_func('hexfile'), device=get_arg_func('device'), speed=get_arg_func('interface-speed-khz'), serial_interface=get_arg_func('serial-interface'), reset_delay_millis=str(get_arg_func('reset-delay-millis')) ) with open(tmpfile.name, 'w') as tempfile_handle: tempfile_handle.write(expanded_script_file) return '{} -CommanderScript {}'.format(self.get_arg_covariant(arguments, 'exe', 'JLinkExe'), tmpfile.name)
def pytest_nanaimo_fixture_type() -> typing.Type['nanaimo.fixtures.Fixture']: return ProgramUploader