Skip to content

Commit

Permalink
Add device cli commands
Browse files Browse the repository at this point in the history
Signed-off-by: Karel Blavka <[email protected]>
  • Loading branch information
blavka committed Jan 24, 2025
1 parent f4d9c2c commit 48fd6e6
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 0 deletions.
32 changes: 32 additions & 0 deletions hardwario/cli/device/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import click
from hardwario.device.nrfjprog import NRFJProg, DEFAULT_JLINK_SPEED_KHZ
from hardwario.cli.device import command


@click.group(name='device', help='Commands for devices.')
@click.pass_context
def cli(ctx):
pass


def create_group(family: str):
@cli.group(name=family.lower(), help=f'Commands for {family} devices.')
@click.option('--jlink-sn', '-n', type=int, metavar='SERIAL_NUMBER', help='JLink serial number')
@click.option('--jlink-speed', type=int, metavar="SPEED", help='JLink clock speed in kHz', default=DEFAULT_JLINK_SPEED_KHZ, show_default=True)
@click.pass_context
def group(ctx, jlink_sn, jlink_speed):
ctx.obj['prog'] = NRFJProg(family, jlink_sn=jlink_sn, jlink_speed=jlink_speed)

command.nrf_flash(group)
command.nrf_erase(group)
command.nrf_reset(group)
command.nrf_console(group, family)

if family in ['nRF91']:
command.nrf_modem_flash(group)

return group


for family in ['nRF51', 'nRF52', 'nRF53', 'nRF54H', 'nRF54L', 'nRF91']:
create_group(family)
120 changes: 120 additions & 0 deletions hardwario/cli/device/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import os
import pylink
import click
from hardwario.cli.console import Console
from hardwario.cli.console.connector import FileLogConnector
from hardwario.cli.chester.validate import validate_hex_file
from hardwario.device.connector.jlink import PyLinkRTTConnector
from hardwario.chester.utils import find_hex


def nrf_flash(cli: click.Group):
@cli.command('flash')
@click.option('--halt', is_flag=True, help='Halt program.')
@click.argument('hex_file', metavar='HEX_FILE_OR_ID', callback=validate_hex_file, default=find_hex('.', no_exception=True))
@click.pass_context
def command_flash(ctx, halt, hex_file):
'''Flash application firmware (preserves UICR area).'''
click.echo(f'File: {hex_file}')

def progress(text, ctx={'len': 0}):
if ctx['len']:
click.echo('\r' + (' ' * ctx['len']) + '\r', nl=False)
if not text:
return
ctx['len'] = len(text)
click.echo(text, nl=text == 'Successfully completed')

with ctx.obj['prog'] as prog:
prog.program(hex_file, halt, progress=progress)

return command_flash


def nrf_erase(cli: click.Group):
@cli.command('erase')
@click.option('--all', is_flag=True, help='Erase application firmware incl. UICR area.')
@click.pass_context
def command_erase(ctx, all):
'''Erase application firmware w/o UICR area.'''
with ctx.obj['prog'] as prog:
if all:
prog.erase_all()
else:
prog.erase_flash()
click.echo('Successfully completed')

return command_erase


def nrf_reset(cli: click.Group):
@cli.command('reset')
@click.option('--halt', is_flag=True, help='Halt program.')
@click.pass_context
def command_reset(ctx, halt):
'''Reset application firmware.'''
with ctx.obj['prog'] as prog:
prog.reset()
if halt:
prog.halt()
click.echo('Successfully completed')

return command_reset


def nrf_console(cli: click.Group, family):

default_history_file = os.path.expanduser(f"~/.hio_{family.lower()}_history")
default_console_file = os.path.expanduser(f"~/.hio_{family.lower()}_console")

@cli.command('console')
@click.option('--reset', is_flag=True, help='Reset application firmware.')
@click.option('--latency', type=int, help='Latency for RTT readout in ms.', show_default=True, default=50)
@click.option('--history-file', type=click.Path(writable=True), show_default=True, default=default_history_file)
@click.option('--console-file', type=click.Path(writable=True), show_default=True, default=default_console_file)
@click.pass_context
def command_console(ctx, reset, latency, history_file, console_file):
'''Start interactive console for shell and logging.'''

with ctx.obj['prog'] as prog:
if reset:
prog.reset()
prog.go()

device_version = str(prog.read_device_info()[0])
end = device_version.rfind('_')
chip_name = device_version[len('DeviceVersion.'):end]

jlink = pylink.JLink()
jlink.open(serial_no=prog.get_serial_number())
jlink.set_speed(prog.get_speed())
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
jlink.connect(chip_name)

connector = PyLinkRTTConnector(jlink, latency=latency)

if console_file:
connector = FileLogConnector(connector, console_file)

console = Console(connector, history_file=history_file)
console.run()

return command_console


def nrf_modem_flash(cli: click.Group):
@cli.command('modem-flash')
@click.argument('file', metavar='ZIP_FILE', type=click.Path(readable=True))
@click.pass_context
def command_modem_flash(ctx, file):
'''Flash SiP modem firmware.'''
# https://www.nordicsemi.com/Products/Development-hardware/nRF9160-DK/Download
if not file.endswith('.zip'):
raise click.ClickException('File must be a ZIP archive')

with ctx.obj['prog'] as prog:
click.echo(f'Flash: {file}')
prog.program(file)
click.echo('Successfully completed')

return command_modem_flash

0 comments on commit 48fd6e6

Please sign in to comment.