Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 49abc2c92277
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5c27fe47f8db
Choose a head ref
  • 1 commit
  • 6 files changed
  • 1 contributor

Commits on Aug 2, 2019

  1. applet.interface.jtag_probe: add explicit support for sideband signals.

    One example of a sideband signal is TRST#, already present, but other
    ones are also useful, for example SRST#, device programming signals
    like PROGRAM#, and also alternative transport layers, which might use
    these sidebands internally.
    
    A number of pulse_trst() calls has been removed from other applets
    on the grounds that the TRST# driver (if TRST# is present) is enabled
    by default, and so TMS-driven reset should be sufficient for most
    use cases. The reset argument to JTAGProbeApplet.run() may later be
    exposed via a command line argument as well, in case some devices
    turn out to need an explicit TRST# pulse.
    whitequark committed Aug 2, 2019
    Copy the full SHA
    5c27fe4 View commit details
4 changes: 2 additions & 2 deletions software/glasgow/applet/__init__.py
Original file line number Diff line number Diff line change
@@ -49,8 +49,8 @@ def build(self, target):
def add_run_arguments(cls, parser, access):
access.add_run_arguments(parser)

async def run_lower(self, cls, device, args):
return await super(cls, self).run(device, args)
async def run_lower(self, cls, device, args, **kwargs):
return await super(cls, self).run(device, args, **kwargs)

async def run(self, device, args):
raise NotImplementedError
3 changes: 1 addition & 2 deletions software/glasgow/applet/debug/arc/__init__.py
Original file line number Diff line number Diff line change
@@ -132,11 +132,10 @@ def add_run_arguments(cls, parser, access):
help="select TAP #INDEX for communication (default: %(default)s)")

async def run(self, device, args):
jtag_iface = await super().run(device, args)
jtag_iface = await self.run_lower(DebugARCApplet, device, args)
tap_iface = await jtag_iface.select_tap(args.tap_index)
if not tap_iface:
raise GlasgowAppletError("cannot select TAP #%d" % args.tap_index)

return ARCDebugInterface(tap_iface, self.logger)

async def interact(self, device, args, arc_iface):
3 changes: 1 addition & 2 deletions software/glasgow/applet/debug/mips/__init__.py
Original file line number Diff line number Diff line change
@@ -829,11 +829,10 @@ def add_run_arguments(cls, parser, access):
help="select TAP #INDEX for communication (default: %(default)s)")

async def run(self, device, args):
jtag_iface = await super().run(device, args)
jtag_iface = await self.run_lower(DebugMIPSApplet, device, args)
tap_iface = await jtag_iface.select_tap(args.tap_index)
if not tap_iface:
raise GlasgowAppletError("cannot select TAP #%d" % args.tap_index)

return await EJTAGDebugInterface(tap_iface, self.logger)

@classmethod
100 changes: 75 additions & 25 deletions software/glasgow/applet/interface/jtag_probe/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
# Ref: IEEE Std 1149.1-2001
# Accession: G00018

# Transport layers
# ----------------
#
# The industry has defined a number of custom JTAG transport layers, such as cJTAG, Spy-Bi-Wire,
# and so on. As long as these comprise a straightforward serialization of the four JTAG signals,
# it is possible to reuse most of this applet by defining a TransportLayerProbeAdapter, with
# the same interface as JTAGProbeAdapter.
#
# Sideband signals
# ----------------
#
# Devices using JTAG for programming and debugging (as opposed to boundary scan) often define
# a number of sideband input or output signals, such as a reset signal or a program success signal.
# The probe driver allows setting or retrieving the state of up to 8 auxiliary signals provided
# by the probe adapter, synchronized to the normal JTAG command stream.
#
# By convention, aux[0:1] are {TRST#.Z, TRST#.O} if the probe adapter provides TRST#.

import struct
import logging
import asyncio
@@ -41,12 +59,10 @@ def __init__(self, pads):
if hasattr(pads, "trst_t"):
self.sync += [
pads.trst_t.oe.eq(~self.trst_z),
pads.trst_t.o.eq(~self.trst)
pads.trst_t.o.eq(~self.trst_o)
]


# Other kinds of adapters are possible, e.g. cJTAG or Spy-Bi-Wire. Applets providing other adapters
# would reuse the interface of JTAGProbeAdapter.
class JTAGProbeAdapter(Module):
def __init__(self, bus, period_cyc):
self.stb = Signal()
@@ -55,8 +71,8 @@ def __init__(self, bus, period_cyc):
self.tms = Signal()
self.tdo = Signal()
self.tdi = Signal()
self.trst_z = bus.trst_z
self.trst_o = bus.trst_o
self.aux_i = C(0)
self.aux_o = Cat(bus.trst_z, bus.trst_o)

###

@@ -92,18 +108,19 @@ def __init__(self, bus, period_cyc):


CMD_MASK = 0b11110000
CMD_SET_TRST = 0b00000000
CMD_SHIFT_TMS = 0b00010000
CMD_SHIFT_TDIO = 0b00100000
# CMD_SET_TRST
BIT_TRST_Z = 0b01
BIT_TRST_O = 0b10
CMD_SHIFT_TMS = 0b00000000
CMD_SHIFT_TDIO = 0b00010000
CMD_GET_AUX = 0b00100000
CMD_SET_AUX = 0b00110000
# CMD_SHIFT_{TMS,TDIO}
BIT_DATA_OUT = 0b0001
BIT_DATA_IN = 0b0010
BIT_LAST = 0b0100
# CMD_SHIFT_TMS
BIT_TDI = 0b1000
# CMD_SET_AUX
BIT_TRST_Z = 0b01
BIT_TRST_O = 0b10


class JTAGProbeDriver(Module):
@@ -124,13 +141,27 @@ def __init__(self, adapter, out_fifo, in_fifo):
)
)
self.fsm.act("COMMAND",
If((cmd & CMD_MASK) == CMD_SET_TRST,
NextValue(adapter.trst_z, (cmd & BIT_TRST_Z) != 0),
NextValue(adapter.trst_o, (cmd & BIT_TRST_O) != 0),
NextState("RECV-COMMAND")
).Elif(((cmd & CMD_MASK) == CMD_SHIFT_TMS) |
If(((cmd & CMD_MASK) == CMD_SHIFT_TMS) |
((cmd & CMD_MASK) == CMD_SHIFT_TDIO),
NextState("RECV-COUNT-1")
).Elif((cmd & CMD_MASK) == CMD_GET_AUX,
NextState("SEND-AUX")
).Elif((cmd & CMD_MASK) == CMD_SET_AUX,
NextState("RECV-AUX")
)
)
self.fsm.act("SEND-AUX",
If(in_fifo.writable,
in_fifo.we.eq(1),
in_fifo.din.eq(adapter.aux_i),
NextState("RECV-COMMAND")
)
)
self.fsm.act("RECV-AUX",
If(out_fifo.readable,
out_fifo.re.eq(1),
NextValue(adapter.aux_o, out_fifo.dout),
NextState("RECV-COMMAND")
)
)
self.fsm.act("RECV-COUNT-1",
@@ -233,11 +264,12 @@ def __init__(self, message, old_state, new_state):


class JTAGProbeInterface:
def __init__(self, interface, logger, __name__=__name__):
def __init__(self, interface, logger, has_trst=False, __name__=__name__):
self.lower = interface
self._logger = logger
self._level = logging.DEBUG if self._logger.name == __name__ else logging.TRACE

self.has_trst = has_trst
self._state = "Unknown"
self._current_ir = None

@@ -249,15 +281,31 @@ def _log_h(self, message, *args):

# Low-level operations

async def flush(self):
self._log_l("flush")
await self.lower.flush()

async def set_aux(self, value):
self._log_l("set aux=%s", format(value, "08b"))
await self.lower.write(struct.pack("<BB",
CMD_SET_AUX, value))

async def get_aux(self):
await self.lower.write(struct.pack("<B",
CMD_GET_AUX))
value, = await self.lower.read(1)
self._log_l("get aux=%s", format(value, "08b"))
return value

async def set_trst(self, active):
if not self.has_trst:
raise JTAGProbeError("cannot set TRST#: adapter does not provide TRST#")
if active is None:
self._log_l("set trst=z")
await self.lower.write(struct.pack("<B",
CMD_SET_TRST|BIT_TRST_Z))
await self.set_aux(BIT_TRST_Z)
else:
self._log_l("set trst=%d", active)
await self.lower.write(struct.pack("<B",
CMD_SET_TRST|(BIT_TRST_O if active else 0)))
await self.set_aux(BIT_TRST_O if active else 0)

async def shift_tms(self, tms_bits, tdi=False):
tms_bits = bits(tms_bits)
@@ -762,12 +810,14 @@ def build(self, target, args):
period_cyc=target.sys_clk_freq // (args.frequency * 1000),
))

async def run(self, device, args, reset=True):
async def run(self, device, args, reset=False):
iface = await device.demultiplexer.claim_interface(self, self.mux_interface, args)
jtag_iface = JTAGProbeInterface(iface, self.logger)
jtag_iface = JTAGProbeInterface(iface, self.logger, has_trst=args.pin_trst is not None)
if reset:
# If we have a defined TRST#, enable the driver and reset the TAPs to a good state.
await jtag_iface.pulse_trst()
if jtag_iface.has_trst:
await jtag_iface.pulse_trst()
else:
await jtag_iface.test_reset()
return jtag_iface

@classmethod
4 changes: 1 addition & 3 deletions software/glasgow/applet/interface/jtag_svf/__init__.py
Original file line number Diff line number Diff line change
@@ -184,9 +184,7 @@ class JTAGSVFApplet(JTAGProbeApplet, name="jtag-svf"):
"""

async def run(self, device, args):
jtag_iface = await super().run(device, args)
await jtag_iface.pulse_trst()

jtag_iface = await self.run_lower(JTAGSVFApplet, device, args)
return SVFInterface(jtag_iface, self.logger, args.frequency * 1000)

@classmethod
5 changes: 1 addition & 4 deletions software/glasgow/applet/program/xc9500xl/__init__.py
Original file line number Diff line number Diff line change
@@ -499,13 +499,10 @@ def add_run_arguments(cls, parser, access):
help="select TAP #INDEX for communication (default: %(default)s)")

async def run(self, device, args):
jtag_iface = await super().run(device, args)
await jtag_iface.pulse_trst()

jtag_iface = await self.run_lower(ProgramXC9500XLApplet, device, args)
tap_iface = await jtag_iface.select_tap(args.tap_index)
if not tap_iface:
raise GlasgowAppletError("cannot select TAP #%d" % args.tap_index)

return XC9500XLInterface(tap_iface, self.logger, args.frequency * 1000)

@classmethod