Skip to content

Commit

Permalink
driver: Add driver for Dediprog SPI-flash emulator
Browse files Browse the repository at this point in the history
The EM100-pro is a SPI-flash emulator which supports a variety of chips.
It can be used to provide an image to a booting system.

Add a driver which allows images to be loaded ready for use.

Signed-off-by: Simon Glass <[email protected]>
  • Loading branch information
sjg20 committed Aug 22, 2024
1 parent 1ab0abd commit 6c1425f
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 0 deletions.
37 changes: 37 additions & 0 deletions doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,34 @@ NetworkDediprogFlasher
A :any:`NetworkDediprogFlasher` describes a `DediprogFlasher`_ available on a
remote computer.

SFEmulator
~~~~~~~~~~
A :any:`SFEmulator` resource is used to configure the parameters for a
SPI-flash emulator. This allows a DUT's SPI flash to be replaced or
overridden with a USB-connected emulator, which is much faster to load than
reprogramming the DUT's actual SPI flash.

So far only the Dediprog EM100-PRO is supported, so there is no 'model' property
defined.

Arguments:
- serial (str): Serial number of the device
- chip (str): SPI-flash chip to emulate

.. code-block:: yaml
SFEmulator:
serial: DP025143
chip: W25Q64CV
Used by:
- `SFEmulatorDriver`_

NetworkSFEmulator
~~~~~~~~~~~~~~~~~
A :any:`NetworkSFEmulator` describes a `SFEmulator`_ available on a
remote computer.

XenaManager
~~~~~~~~~~~
A :any:`XenaManager` resource describes a *Xena Manager* instance which is the
Expand Down Expand Up @@ -3052,6 +3080,15 @@ devices. It is assumed that the device flashing is an exporter wired, via a
*Dediprog SF100 SPI NOR Flash Programmer* for instance, to the device being
flashed.

SFEmulatorDriver
~~~~~~~~~~~~~~~~
The :any:`SFEmulatorDriver` is used to emulate a SPI-flash device on the DUT.

Binds to:
flasher:
- `SFEmulator`_
- `NetworkSFEmulator`_

XenaDriver
~~~~~~~~~~
The :any:`XenaDriver` allows to use Xena networking test equipment.
Expand Down
1 change: 1 addition & 0 deletions labgrid/driver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@
from .deditecrelaisdriver import DeditecRelaisDriver
from .dediprogflashdriver import DediprogFlashDriver
from .httpdigitaloutput import HttpDigitalOutputDriver
from .sfemulatordriver import SFEmulatorDriver
98 changes: 98 additions & 0 deletions labgrid/driver/sfemulatordriver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import subprocess
from threading import Thread
import time

import attr
from .common import Driver
from ..factory import target_factory
from ..step import step
from ..util.helper import processwrapper, ProcessRunner
from ..util.managedfile import ManagedFile

@target_factory.reg_driver
@attr.s(eq=False)
class SFEmulatorDriver(Driver):
"""Provides access to em100 features
Args:
bindings (dict): driver to use with
_proc (subprocess.Popen): Process running em100 (used only in trace
mode)
_trace (str): Filename of trace file, if enabled
_thread (Thread): Thread which monitors the subprocess for errors
"""
bindings = {
'emul': {'SFEmulator', 'NetworkSFEmulator'},
}
trace = attr.ib(default=False, validator=attr.validators.instance_of(bool))

def __attrs_post_init__(self):
super().__attrs_post_init__()
if self.target.env:
self.tool = self.target.env.config.get_tool('em100')
else:
self.tool = 'em100'
self._trace = None
self._thread = None

@Driver.check_active
@step(title='write_image', args=['filename'])
def write_image(self, filename):
'''Write an image to the SPI-flash emulator
Args:
filename (str): Filename to write
'''
self._trace = None # Provide this filename later

mf = ManagedFile(filename, self.emul)
mf.sync_to_resource()
cmd = self.emul.command_prefix + [
self.tool,
'-x', str(self.emul.serial),
'-s',
'-p', 'LOW',
'-c', self.emul.chip,
'-d', mf.get_remote_path(),
'-r',
]

# For trace mode, start a process which will run for the duration of
# the Labgrid client, all going well
if self._trace:
cmd.append('-t')
logfile = open(self._trace, 'w')
self._thread = Thread(target=self.monitor_thread,
args=(cmd, logfile))
self._thread.daemon = True
self._thread.start()
else:
processwrapper.check_output(cmd)

def __str__(self):
return f'SFEmulatorDriver({self.emul.serial})'

def monitor_thread(self, cmd, logfile):
"""Thread to monitor the em100 process
This is mostly just here to check if it dies, so a useful error can be
shown.
Args:
cmd (list of str): Command to run
logfile (file): Output file for trace log
"""
proc = ProcessRunner(cmd, stdin=subprocess.DEVNULL, stdout=logfile)
while True:
if proc.check():
break
time.sleep(.1)
try:
proc.kill()
proc.finish()
except subprocess.CalledProcessError as exc:
# If there is something wrong, the error will be in the logfile, so
# print it out
print('em100 failed', exc.returncode)
with open(self._trace, 'r') as inf:
print('err', inf.read(1024))
19 changes: 19 additions & 0 deletions labgrid/remote/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,25 @@ def _get_params(self):

exports["YKUSHPowerPort"] = YKUSHPowerPortExport

@attr.s(eq=False)
class SFEmulatorExport(ResourceExport):
"""ResourceExport for SFEmulator devices"""

def __attrs_post_init__(self):
super().__attrs_post_init__()
local_cls_name = self.cls
self.data['cls'] = f"Network{local_cls_name}"
from ..resource import sfemulator
local_cls = getattr(sfemulator, local_cls_name)
self.local = local_cls(target=None, name=None, **self.local_params)

def _get_params(self):
return {
"host": self.host,
**self.local_params
}

exports["SFEmulator"] = SFEmulatorExport

class Exporter:
def __init__(self, config) -> None:
Expand Down
1 change: 1 addition & 0 deletions labgrid/resource/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@
from .httpdigitalout import HttpDigitalOutput
from .sigrok import SigrokDevice
from .fastboot import AndroidNetFastboot
from .sfemulator import SFEmulator, NetworkSFEmulator
32 changes: 32 additions & 0 deletions labgrid/resource/sfemulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import attr

from ..factory import target_factory
from .common import NetworkResource, Resource

@target_factory.reg_resource
@attr.s(eq=False)
class SFEmulator(Resource):
""""This resource describes a Dediprog em100 SPI-Flash Emulator
This provides serial consoles along with reset control
Args:
serial (str): serial number of the em100 device, e.g. DP025143
chip (str): SPI-flash chip to emulate, e.g. W25Q64CV
"""
serial = attr.ib(validator=attr.validators.instance_of(str))
chip = attr.ib(validator=attr.validators.instance_of(str))

@target_factory.reg_resource
@attr.s(eq=False)
class NetworkSFEmulator(NetworkResource):
""""This resource describes a remote Dediprog em100 SPI-Flash Emulator
This provides serial consoles along with reset control
Args:
serial (str): serial number of the em100 device, e.g. DP025143
chip (str): SPI-flash chip to emulate, e.g. W25Q64CV
"""
serial = attr.ib(validator=attr.validators.instance_of(str))
chip = attr.ib(validator=attr.validators.instance_of(str))

0 comments on commit 6c1425f

Please sign in to comment.