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: whitequark/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 466ba674e053
Choose a base ref
...
head repository: whitequark/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: afd5f7a0a661
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 19, 2018

  1. applet.jtag: use minimal path through TAP state machine.

    It is important for some cores (e.g. ARC) to not unnecessarily enter
    Run-Test/Idle, as this can initiate actions (e.g. R/W transaction.)
    whitequark committed Nov 19, 2018
    Copy the full SHA
    1f6a504 View commit details
  2. Copy the full SHA
    afd5f7a View commit details
Showing with 42 additions and 6 deletions.
  1. +32 −6 software/glasgow/applet/jtag/__init__.py
  2. +10 −0 software/glasgow/applet/jtag/arc.py
38 changes: 32 additions & 6 deletions software/glasgow/applet/jtag/__init__.py
Original file line number Diff line number Diff line change
@@ -321,6 +321,8 @@ async def enter_run_test_idle(self):
await self.shift_tms("10")
elif self._state in ("Pause-IR", "Pause-DR"):
await self.shift_tms("110")
elif self._state in ("Update-IR", "Update-DR"):
await self.shift_tms("0")
else:
assert False
self._state = "Run-Test/Idle"
@@ -331,7 +333,7 @@ async def enter_shift_ir(self):
self._log_l("state %s → Shift-IR", self._state)
if self._state == "Test-Logic-Reset":
await self.shift_tms("01100")
elif self._state == "Run-Test/Idle":
elif self._state in ("Run-Test/Idle", "Update-IR", "Update-DR"):
await self.shift_tms("1100")
else:
assert False
@@ -347,13 +349,25 @@ async def enter_pause_ir(self):
assert False
self._state = "Pause-IR"

async def enter_update_ir(self):
if self._state == "Update-IR": return

self._log_l("state %s → Update-IR", self._state)
if self._state == "Shift-IR":
await self.shift_tms("11")
elif self._state == "Exit1-IR":
await self.shift_tms("1")
else:
assert False
self._state = "Update-IR"

async def enter_shift_dr(self):
if self._state == "Shift-DR": return

self._log_l("state %s → Shift-DR", self._state)
if self._state == "Test-Logic-Reset":
await self.shift_tms("0100")
elif self._state == "Run-Test/Idle":
elif self._state in ("Run-Test/Idle", "Update-IR", "Update-DR"):
await self.shift_tms("100")
else:
assert False
@@ -369,6 +383,18 @@ async def enter_pause_dr(self):
assert False
self._state = "Pause-DR"

async def enter_update_dr(self):
if self._state == "Update-DR": return

self._log_l("state %s → Update-DR", self._state)
if self._state == "Shift-DR":
await self.shift_tms("11")
elif self._state == "Exit1-DR":
await self.shift_tms("1")
else:
assert False
self._state = "Update-DR"

# High-level register manipulation

async def test_reset(self):
@@ -392,13 +418,13 @@ async def write_ir(self, data):
self._log_h("write ir=<%s>", data.to01())
await self.enter_shift_ir()
await self.shift_tdi(data)
await self.enter_run_test_idle()
await self.enter_update_ir()

async def exchange_dr(self, data):
self._log_h("exchange dr")
await self.enter_shift_dr()
data = await self.shift_tdio(data)
await self.enter_run_test_idle()
await self.enter_update_dr()
return data

async def read_dr(self, count, idempotent=False):
@@ -408,7 +434,7 @@ async def read_dr(self, count, idempotent=False):
# Shift what we just read back in. This is useful to avoid disturbing any bits
# in R/W DRs when we go through Update-DR.
await self.shift_tdi(data)
await self.enter_run_test_idle()
await self.enter_update_dr()
if idempotent:
self._log_h("read idempotent dr=<%s>", data.to01())
else:
@@ -419,7 +445,7 @@ async def write_dr(self, data):
self._log_h("write dr=<%s>", data.to01())
await self.enter_shift_dr()
await self.shift_tdi(data)
await self.enter_run_test_idle()
await self.enter_update_dr()

# Specialized operations

10 changes: 10 additions & 0 deletions software/glasgow/applet/jtag/arc.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,14 @@
# Ref: Microchip MEC1609 Mixed Signal Mobile Embedded Flash ARC EC BC-Link/VLPC Base Component
# Document Number: DS00002485A

# The ARC JTAG TAP core has an important quirk: all transactions are initiated by a TCK pulse
# in Run-Test/Idle state:
#
# The Run-Test/Idle state always precedes the Test-Logic-Reset, Update-DR and Update-IR states
# on the rising edge of TCK when TMS is low. This state is employed to initiate a read/write
# access or place the JTAG module in the idle state. The read/write access defined by the
# address, data and command registers only occurs once on entry to Run-Test/Idle.

import logging
import argparse

@@ -60,6 +68,7 @@ async def read(self, address, space):
await self.lower.write_dr(dr_address.to_bitarray())
await self.lower.write_ir(IR_TXN_COMMAND)
await self.lower.write_dr(dr_txn_command)
await self.lower.run_test_idle(1)
await self._wait_txn()
await self.lower.write_ir(IR_DATA)
dr_data_bits = await self.lower.read_dr(32)
@@ -86,6 +95,7 @@ async def write(self, address, data, space):
await self.lower.write_dr(dr_data.to_bitarray())
await self.lower.write_ir(IR_TXN_COMMAND)
await self.lower.write_dr(dr_txn_command)
await self.lower.run_test_idle(1)
await self._wait_txn()

async def set_halted(self, halted):